Skip to content

Commit

Permalink
Support var overrides for manage command
Browse files Browse the repository at this point in the history
Signed-off-by: Ondrej Fabry <ondrej.fabry@pantheon.tech>
  • Loading branch information
ondrej-fabry committed Apr 20, 2023
1 parent a99a31b commit 459be42
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 69 deletions.
126 changes: 59 additions & 67 deletions cmd/swctl/cmd_manage.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"github.com/gookit/color"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"go.ligato.io/vpp-agent/v3/client"
"go.ligato.io/vpp-agent/v3/pkg/models"
"google.golang.org/protobuf/encoding/protojson"
Expand All @@ -32,6 +31,7 @@ type ManageOptions struct {
Force bool
Offset int
DryRun bool
Vars map[string]string
}

func NewManageCmd(cli Cli) *cobra.Command {
Expand All @@ -58,6 +58,7 @@ func NewManageCmd(cli Cli) *cobra.Command {
cmd.PersistentFlags().StringVar(&opts.Target, "target", "", "Location of target config file base")
cmd.PersistentFlags().StringVar(&opts.Format, "format", "", "Format for the output (yaml, json, proto, go template..)")
cmd.PersistentFlags().BoolVar(&opts.DryRun, "dryrun", false, "Run without actually modifying anything")
cmd.PersistentFlags().StringToStringVar(&opts.Vars, "var", nil, "Override variable values (--var VAR_NAME=value)")

return cmd
}
Expand Down Expand Up @@ -148,10 +149,37 @@ func runManageCmd(cli Cli, opts ManageOptions, args []string) error {

// repeat for given count
for i := 0; i < int(opts.Count); i++ {
vars, err := renderEntityVars(entity, i+opts.Offset)
idx := i + opts.Offset
id := idx + 1

// prepare vars
evars := map[string]string{
"IDX": fmt.Sprint(idx),
"ID": fmt.Sprint(id),
}
// apply overrides
for k, v := range opts.Vars {
if isBuiltinVar(k) {
return fmt.Errorf("cannot override internal variables ID and IDX")
}
var ok bool
for _, evar := range entity.Vars {
if k == evar.Name {
ok = true
break
}
}
if !ok {
return fmt.Errorf("override for variable %q that is not defined for entity", k)
}
evars[k] = v
}
vars, err := renderEntityVars(entity, evars)
if err != nil {
return fmt.Errorf("failed to render vars (idx: %v): %w", i, err)
}

// generate config
config, err := renderEntityConfig(entity, vars)
if err != nil {
return fmt.Errorf("failed to render config (idx: %v): %w", i, err)
Expand Down Expand Up @@ -330,6 +358,28 @@ var funcMap = map[string]any{
"add": func(a, b int) int {
return a + b
},
"inc": func(a int) int {
return a + 1
},
"dec": func(a int) int {
return a - 1
},
"previp": func(ip string, dec int) (string, error) {
x, err := netip.ParseAddr(ip)
if err != nil {
return "", err
}
if dec <= 0 {
return x.String(), nil
}
for i := 1; i <= dec; i++ {
x = x.Prev()
if !x.IsValid() {
return "", fmt.Errorf("no previous IP: %w", err)
}
}
return x.String(), nil
},
"nextip": func(ip string, inc int) (string, error) {
x, err := netip.ParseAddr(ip)
if err != nil {
Expand All @@ -341,7 +391,7 @@ var funcMap = map[string]any{
for i := 1; i <= inc; i++ {
x = x.Next()
if !x.IsValid() {
return "", fmt.Errorf("no next ip: %w", err)
return "", fmt.Errorf("no next IP: %w", err)
}
}
return x.String(), nil
Expand Down Expand Up @@ -393,14 +443,13 @@ func renderEntityConfig(e Entity, evars map[string]string) (string, error) {
return config, nil
}

func renderEntityVars(e Entity, idx int) (map[string]string, error) {
id := idx + 1
evars := map[string]string{
"IDX": fmt.Sprint(idx),
"ID": fmt.Sprint(id),
}
func renderEntityVars(e Entity, evars map[string]string) (map[string]string, error) {
for _, v := range e.Vars {
tmpl, err := interpolateStr(v.Value, evars)
vv := v.Value
if ov, ok := evars[v.Name]; ok {
vv = ov
}
tmpl, err := interpolateStr(vv, evars)
if err != nil {
return nil, err
}
Expand All @@ -413,32 +462,8 @@ func renderEntityVars(e Entity, idx int) (map[string]string, error) {
return evars, nil
}

func listOptions(str string) []string {
idents, err := interpolate.Identifiers(str)
if err != nil {
logrus.Error(err)
return nil
}
//logrus.Infof("IDENTS: %+v", idents)

var vrs []string
uniq := map[string]struct{}{}

for _, ident := range idents {
if _, ok := uniq[ident]; ok {
continue
}
uniq[ident] = struct{}{}
vrs = append(vrs, ident)
}

return vrs
}

func interpolateStr(str string, vars map[string]string) (string, error) {
env := interpolate.NewMapEnv(vars)
//opts := listOptions(str)
//logrus.Infof("opts: %+v", opts)
output, err := interpolate.Interpolate(env, str)
if err != nil {
return "", err
Expand All @@ -458,36 +483,3 @@ func allModels() []*models.ModelInfo {
}
return knownModels
}

func flagValuesFromActionOptions(set *pflag.FlagSet, entity Entity) map[string]string {
opts := make(map[string]string)
for _, opt := range entity.Vars {
if opt.Type == "" || opt.Type == "string" {
var str string
if set.Changed(opt.Name) {
var err error
str, err = set.GetString(opt.Name)
if err != nil {
str = err.Error()
}
} else {
str = opt.Value
}
opts[opt.Name] = str
}
}
return opts
}

func flagSetFromActionOptions(entity Entity) *pflag.FlagSet {
set := pflag.NewFlagSet(entity.Name, pflag.ContinueOnError)
for _, opt := range entity.Vars {
switch opt.Type {
case "":
fallthrough
case "string":
set.String(opt.Name, opt.Value, opt.Description)
}
}
return set
}
7 changes: 6 additions & 1 deletion cmd/swctl/entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,22 @@ func validateEntity(entity *Entity) error {
return nil
}

// TODO: validate name
// TODO: validate entity name

// validate variables
vars := make(map[string]EntityVar)
for i, v := range entity.Vars {
v.Index = i

// TODO: validate variable name

// check if variable name is unique
if dup, ok := vars[v.Name]; ok {
return fmt.Errorf("duplicate var %v on index %d, previous on index %d", v.Name, i, dup.Index)
}
vars[v.Name] = v

// check if variable value references only variables defined earlier
idents, err := interpolate.Identifiers(v.Value)
if err != nil {
return fmt.Errorf("invalid var reference in value of var %v: %w", v.Name, err)
Expand Down
8 changes: 7 additions & 1 deletion docs/SWCTL.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ swctl manage ENTITY add
swctl manage ENTITY add --offset=100
```

To generate combined config for multiple entites, run:
To generate merged config for multiple entites, run:

```bash
# Generate config for multiple entities
Expand All @@ -155,6 +155,12 @@ To merge an existing config file with generated config, run:
swctl manage ENTITY add --target=config.yaml
```

To override value(s) of a specific entity variable, run:

```bash
swctl manage ENTITY add --var MY_VAR="my-value"
```

#### Config

To manage the configuration of StoneWork and its components, run:
Expand Down

0 comments on commit 459be42

Please sign in to comment.