github.com/kubeshop/testkube@v1.17.23/pkg/tcl/expressionstcl/accessor.go (about) 1 // Copyright 2024 Testkube. 2 // 3 // Licensed as a Testkube Pro file under the Testkube Community 4 // License (the "License"); you may not use this file except in compliance with 5 // the License. You may obtain a copy of the License at 6 // 7 // https://github.com/kubeshop/testkube/blob/main/licenses/TCL.txt 8 9 package expressionstcl 10 11 import ( 12 "fmt" 13 "strings" 14 ) 15 16 type accessor struct { 17 name string 18 fallback *Expression 19 } 20 21 func newAccessor(name string) Expression { 22 // Map values based on wildcard 23 segments := strings.Split(name, ".*") 24 if len(segments) > 1 { 25 return newCall("map", []callArgument{ 26 {expr: newAccessor(strings.Join(segments[0:len(segments)-1], ".*"))}, 27 {expr: NewStringValue("_.value" + segments[len(segments)-1])}, 28 }) 29 } 30 31 // Prepare fallback based on the segments 32 segments = strings.Split(name, ".") 33 var fallback *Expression 34 if len(segments) > 1 { 35 f := newPropertyAccessor( 36 newAccessor(strings.Join(segments[0:len(segments)-1], ".")), 37 segments[len(segments)-1], 38 ) 39 fallback = &f 40 } 41 42 return &accessor{name: name, fallback: fallback} 43 } 44 45 func (s *accessor) Type() Type { 46 return TypeUnknown 47 } 48 49 func (s *accessor) String() string { 50 return s.name 51 } 52 53 func (s *accessor) SafeString() string { 54 return s.String() 55 } 56 57 func (s *accessor) Template() string { 58 return "{{" + s.String() + "}}" 59 } 60 61 func (s *accessor) SafeResolve(m ...Machine) (v Expression, changed bool, err error) { 62 if m == nil { 63 return s, false, nil 64 } 65 66 for i := range m { 67 result, ok, err := m[i].Get(s.name) 68 if ok && err == nil { 69 return result, true, nil 70 } 71 if s.fallback != nil { 72 var err2 error 73 result, ok, err2 = (*s.fallback).SafeResolve(m...) 74 if ok && err2 == nil { 75 return result, true, nil 76 } 77 } 78 if err != nil { 79 return nil, false, fmt.Errorf("error while accessing %s: %s", s.String(), err.Error()) 80 } 81 } 82 return s, false, nil 83 } 84 85 func (s *accessor) Resolve(m ...Machine) (v Expression, err error) { 86 return deepResolve(s, m...) 87 } 88 89 func (s *accessor) Static() StaticValue { 90 return nil 91 } 92 93 func (s *accessor) Accessors() map[string]struct{} { 94 return map[string]struct{}{s.name: {}} 95 } 96 97 func (s *accessor) Functions() map[string]struct{} { 98 return nil 99 }