2021-01-08 10:07:46 +00:00
package yqlib
import (
2022-01-26 22:20:53 +00:00
"container/list"
2021-01-11 03:38:53 +00:00
"fmt"
2021-01-08 10:07:46 +00:00
"os"
2023-05-05 04:13:18 +00:00
"strings"
2021-01-08 10:07:46 +00:00
2022-03-19 23:56:50 +00:00
parse "github.com/a8m/envsubst/parse"
2021-01-08 10:07:46 +00:00
)
2021-01-11 06:13:48 +00:00
type envOpPreferences struct {
2021-01-09 01:06:19 +00:00
StringValue bool
2022-03-19 23:56:50 +00:00
NoUnset bool
NoEmpty bool
FailFast bool
2021-01-09 01:06:19 +00:00
}
2021-01-08 10:07:46 +00:00
2021-02-02 07:17:59 +00:00
func envOperator ( d * dataTreeNavigator , context Context , expressionNode * ExpressionNode ) ( Context , error ) {
2023-04-09 01:14:51 +00:00
envName := expressionNode . Operation . CandidateNode . Value
2021-01-08 10:07:46 +00:00
log . Debug ( "EnvOperator, env name:" , envName )
rawValue := os . Getenv ( envName )
2021-01-13 06:00:53 +00:00
preferences := expressionNode . Operation . Preferences . ( envOpPreferences )
2021-01-09 01:06:19 +00:00
2023-04-09 01:14:51 +00:00
var node * CandidateNode
2021-01-09 01:06:19 +00:00
if preferences . StringValue {
2023-04-09 01:14:51 +00:00
node = & CandidateNode {
Kind : ScalarNode ,
2021-01-09 01:06:19 +00:00
Tag : "!!str" ,
Value : rawValue ,
}
2021-01-11 03:38:53 +00:00
} else if rawValue == "" {
2023-05-05 04:13:18 +00:00
return Context { } , fmt . Errorf ( "value for env variable '%v' not provided in env()" , envName )
2021-01-09 01:06:19 +00:00
} else {
2023-04-09 01:14:51 +00:00
decoder := NewYamlDecoder ( ConfiguredYamlPreferences )
2023-05-05 05:19:58 +00:00
if err := decoder . Init ( strings . NewReader ( rawValue ) ) ; err != nil {
return Context { } , err
}
2023-04-09 01:14:51 +00:00
result , err := decoder . Decode ( )
if err != nil {
return Context { } , err
2021-01-09 01:06:19 +00:00
}
2023-04-09 01:14:51 +00:00
node = result . unwrapDocument ( )
2021-01-09 01:06:19 +00:00
}
log . Debug ( "ENV tag" , node . Tag )
log . Debug ( "ENV value" , node . Value )
log . Debug ( "ENV Kind" , node . Kind )
2023-04-09 01:14:51 +00:00
return context . SingleChildContext ( node ) , nil
2021-01-08 10:07:46 +00:00
}
2022-01-26 22:20:53 +00:00
func envsubstOperator ( d * dataTreeNavigator , context Context , expressionNode * ExpressionNode ) ( Context , error ) {
var results = list . New ( )
2022-03-19 23:56:50 +00:00
preferences := envOpPreferences { }
if expressionNode . Operation . Preferences != nil {
preferences = expressionNode . Operation . Preferences . ( envOpPreferences )
}
parser := parse . New ( "string" , os . Environ ( ) ,
& parse . Restrictions { NoUnset : preferences . NoUnset , NoEmpty : preferences . NoEmpty } )
if preferences . FailFast {
parser . Mode = parse . Quick
} else {
parser . Mode = parse . AllErrors
}
2022-01-26 22:20:53 +00:00
for el := context . MatchingNodes . Front ( ) ; el != nil ; el = el . Next ( ) {
candidate := el . Value . ( * CandidateNode )
2023-04-09 01:14:51 +00:00
node := candidate . unwrapDocument ( )
2022-01-26 22:20:53 +00:00
if node . Tag != "!!str" {
log . Warning ( "EnvSubstOperator, env name:" , node . Tag , node . Value )
return Context { } , fmt . Errorf ( "cannot substitute with %v, can only substitute strings. Hint: Most often you'll want to use '|=' over '=' for this operation" , node . Tag )
}
2022-03-19 23:56:50 +00:00
value , err := parser . Parse ( node . Value )
2022-01-26 22:20:53 +00:00
if err != nil {
return Context { } , err
}
2023-04-09 01:14:51 +00:00
result := candidate . CreateReplacement ( ScalarNode , "!!str" , value )
2022-01-26 22:20:53 +00:00
results . PushBack ( result )
}
return context . ChildContext ( results ) , nil
}