Skip to content

Commit

Permalink
Port subtract template function (#2435)
Browse files Browse the repository at this point in the history
* port subtract function

* release note
  • Loading branch information
hellt authored Jan 31, 2025
1 parent 2ffa074 commit c6f6e39
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 3 deletions.
4 changes: 4 additions & 0 deletions docs/rn/0.63.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,7 @@ Given the sheer blast radius this change brings, we are eager to hear your feedb
### 0.63.2

* update podman dependency to not fail on a `~/.config` dir permissions when using sudo-less operation #2431

### 0.63.3

* added subtract template function that was used in SR OS and was removed with gomplate #2435
3 changes: 2 additions & 1 deletion nodes/vr_sros/sshKey.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"text/template"

log "github.com/sirupsen/logrus"
"github.com/srl-labs/containerlab/utils"
"golang.org/x/crypto/ssh"
)

Expand All @@ -23,7 +24,7 @@ func (s *vrSROS) generateSSHPublicKeysConfig() (io.Reader, error) {

s.prepareSSHPubKeys(&tplData)

t, err := template.New("SSHKeys").Parse(SROSSSHKeysTemplate)
t, err := template.New("SSHKeys").Funcs(utils.TemplateFuncs).Parse(SROSSSHKeysTemplate)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions nodes/vr_sros/ssh_keys.go.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
/configure system security user-params attempts count 64

{{ range $index, $key := .SSHPubKeysRSA }}
/configure system security user-params local-user user "admin" public-keys rsa rsa-key {{ sub 32 $index }} key-value {{ $key }}
/configure system security user-params local-user user "admin" public-keys rsa rsa-key {{ subtract 32 $index }} key-value {{ $key }}
{{ end }}

{{ range $index, $key := .SSHPubKeysECDSA }}
/configure system security user-params local-user user "admin" public-keys ecdsa ecdsa-key {{ sub 32 $index }} key-value {{ $key }}
/configure system security user-params local-user user "admin" public-keys ecdsa ecdsa-key {{ subtract 32 $index }} key-value {{ $key }}
{{ end }}
174 changes: 174 additions & 0 deletions utils/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ package utils

import (
"encoding/json"
"fmt"
"math"
"reflect"
"strconv"
"strings"
"text/template"
)

var TemplateFuncs = template.FuncMap{
"ToJSON": toJson,
"ToJSONPretty": toJsonPretty,
"add": add,
"subtract": subtract,
}

func toJson(v any) string {
Expand All @@ -25,3 +31,171 @@ func toJsonPretty(v any, prefix string, indent string) string {
func add(a, b int) int {
return a + b
}

// subtract b from a
// copy from gomplate.
func subtract(a, b any) (any, error) {
if containsFloat(a, b) {
fa, err := ToFloat64(a)
if err != nil {
return nil, fmt.Errorf("expected a number: %w", err)
}

fb, err := ToFloat64(b)
if err != nil {
return nil, fmt.Errorf("expected a number: %w", err)
}

return fa - fb, nil
}

ia, err := ToInt64(a)
if err != nil {
return nil, fmt.Errorf("expected a number: %w", err)
}

ib, err := ToInt64(b)
if err != nil {
return nil, fmt.Errorf("expected a number: %w", err)
}

return ia - ib, nil
}

func containsFloat(n ...any) bool {
c := false
for _, v := range n {
if isFloat(v) {
return true
}
}
return c
}

func isFloat(n any) bool {
switch i := n.(type) {
case float32, float64:
return true
case string:
_, err := strconv.ParseFloat(i, 64)
if err != nil {
return false
}
if isInt(i) {
return false
}
return true
}
return false
}

func isInt(n any) bool {
switch i := n.(type) {
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
return true
case string:
_, err := strconv.ParseInt(i, 0, 64)
return err == nil
}
return false
}

func ToFloat64(v interface{}) (float64, error) {
if str, ok := v.(string); ok {
return strToFloat64(str)
}

val := reflect.Indirect(reflect.ValueOf(v))
switch val.Kind() {
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
return float64(val.Int()), nil
case reflect.Uint8, reflect.Uint16, reflect.Uint32:
return float64(val.Uint()), nil
case reflect.Uint, reflect.Uint64:
return float64(val.Uint()), nil
case reflect.Float32, reflect.Float64:
return val.Float(), nil
case reflect.Bool:
if val.Bool() {
return 1, nil
}
return 0, nil
default:
return 0, fmt.Errorf("could not convert %v to float64", v)
}
}

func strToInt64(str string) (int64, error) {
if strings.Contains(str, ",") {
str = strings.ReplaceAll(str, ",", "")
}

iv, err := strconv.ParseInt(str, 0, 64)
if err != nil {
// maybe it's a float?
var fv float64
fv, err = strconv.ParseFloat(str, 64)
if err != nil {
return 0, fmt.Errorf("could not convert %q to int64: %w", str, err)
}

return ToInt64(fv)
}

return iv, nil
}

func ToInt64(v interface{}) (int64, error) {
if str, ok := v.(string); ok {
return strToInt64(str)
}

val := reflect.Indirect(reflect.ValueOf(v))
switch val.Kind() {
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
return val.Int(), nil
case reflect.Uint8, reflect.Uint16, reflect.Uint32:
//nolint:gosec // G115 isn't applicable, this is a Uint32 at most
return int64(val.Uint()), nil
case reflect.Uint, reflect.Uint64:
tv := val.Uint()

if tv > math.MaxInt64 {
return 0, fmt.Errorf("could not convert %d to int64, would overflow", tv)
}

return int64(tv), nil
case reflect.Float32, reflect.Float64:
return int64(val.Float()), nil
case reflect.Bool:
if val.Bool() {
return 1, nil
}

return 0, nil
default:
return 0, fmt.Errorf("could not convert %v to int64", v)
}
}

func strToFloat64(str string) (float64, error) {
if strings.Contains(str, ",") {
str = strings.ReplaceAll(str, ",", "")
}

// this is inefficient, but it's the only way I can think of to
// properly convert octal integers to floats
iv, err := strconv.ParseInt(str, 0, 64)
if err != nil {
// ok maybe it's a float?
var fv float64
fv, err = strconv.ParseFloat(str, 64)
if err != nil {
return 0, fmt.Errorf("could not convert %q to float64: %w", str, err)
}

return fv, nil
}

return float64(iv), nil
}

0 comments on commit c6f6e39

Please sign in to comment.