mirror of
				https://github.com/taigrr/yq
				synced 2025-01-18 04:53:17 -08:00 
			
		
		
		
	Env Ops!
This commit is contained in:
		
							parent
							
								
									aabed1a237
								
							
						
					
					
						commit
						644063646e
					
				| @ -1,21 +1,76 @@ | |||||||
| 
 | 
 | ||||||
|  | ## Read string environment variable | ||||||
|  | Running | ||||||
|  | ```bash | ||||||
|  | myenv="cat meow" yq eval --null-input '.a = env(myenv)' | ||||||
|  | ``` | ||||||
|  | will output | ||||||
|  | ```yaml | ||||||
|  | a: cat meow | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## Read boolean environment variable | ||||||
|  | Running | ||||||
|  | ```bash | ||||||
|  | myenv="true" yq eval --null-input '.a = env(myenv)' | ||||||
|  | ``` | ||||||
|  | will output | ||||||
|  | ```yaml | ||||||
|  | a: true | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## Read numeric environment variable | ||||||
|  | Running | ||||||
|  | ```bash | ||||||
|  | myenv="12" yq eval --null-input '.a = env(myenv)' | ||||||
|  | ``` | ||||||
|  | will output | ||||||
|  | ```yaml | ||||||
|  | a: 12 | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## Read yaml environment variable | ||||||
|  | Running | ||||||
|  | ```bash | ||||||
|  | myenv="{b: fish}" yq eval --null-input '.a = env(myenv)' | ||||||
|  | ``` | ||||||
|  | will output | ||||||
|  | ```yaml | ||||||
|  | a: {b: fish} | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
| ## Read boolean environment variable as a string | ## Read boolean environment variable as a string | ||||||
| Running | Running | ||||||
| ```bash | ```bash | ||||||
| myenv="true" yq eval --null-input 'strenv(myenv)' | myenv="true" yq eval --null-input '.a = strenv(myenv)' | ||||||
| ``` | ``` | ||||||
| will output | will output | ||||||
| ```yaml | ```yaml | ||||||
| 12 | a: "true" | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ## Read numeric environment variable as a string | ## Read numeric environment variable as a string | ||||||
| Running | Running | ||||||
| ```bash | ```bash | ||||||
| myenv="12" yq eval --null-input 'strenv(myenv)' | myenv="12" yq eval --null-input '.a = strenv(myenv)' | ||||||
| ``` | ``` | ||||||
| will output | will output | ||||||
| ```yaml | ```yaml | ||||||
| 12 | a: "12" | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## Dynamic key lookup with environment variable | ||||||
|  | Given a sample.yml file of: | ||||||
|  | ```yaml | ||||||
|  | cat: meow | ||||||
|  | dog: woof | ||||||
|  | ``` | ||||||
|  | then | ||||||
|  | ```bash | ||||||
|  | myenv="cat" yq eval '.[env(myenv)]' sample.yml | ||||||
|  | ``` | ||||||
|  | will output | ||||||
|  | ```yaml | ||||||
|  | meow | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -48,6 +48,24 @@ will output | |||||||
| frog | frog | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
|  | ## Dynamic keys | ||||||
|  | Expressions within [] can be used to dynamically lookup / calculate keys | ||||||
|  | 
 | ||||||
|  | Given a sample.yml file of: | ||||||
|  | ```yaml | ||||||
|  | b: apple | ||||||
|  | apple: crispy yum | ||||||
|  | banana: soft yum | ||||||
|  | ``` | ||||||
|  | then | ||||||
|  | ```bash | ||||||
|  | yq eval '.[.b]' sample.yml | ||||||
|  | ``` | ||||||
|  | will output | ||||||
|  | ```yaml | ||||||
|  | crispy yum | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
| ## Children don't exist | ## Children don't exist | ||||||
| Nodes are added dynamically while traversing | Nodes are added dynamically while traversing | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										0
									
								
								pkg/yqlib/doc/headers/Env Variable Operators.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								pkg/yqlib/doc/headers/Env Variable Operators.md
									
									
									
									
									
										Normal file
									
								
							| @ -3,13 +3,14 @@ package yqlib | |||||||
| import ( | import ( | ||||||
| 	"container/list" | 	"container/list" | ||||||
| 	"os" | 	"os" | ||||||
|  | 	"strings" | ||||||
| 
 | 
 | ||||||
| 	yaml "gopkg.in/yaml.v3" | 	yaml "gopkg.in/yaml.v3" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // type EnvOpPreferences struct { | type EnvOpPreferences struct { | ||||||
| // 	StringValue bool | 	StringValue bool | ||||||
| // } | } | ||||||
| 
 | 
 | ||||||
| func EnvOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *PathTreeNode) (*list.List, error) { | func EnvOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *PathTreeNode) (*list.List, error) { | ||||||
| 	envName := pathNode.Operation.CandidateNode.Node.Value | 	envName := pathNode.Operation.CandidateNode.Node.Value | ||||||
| @ -17,15 +18,34 @@ func EnvOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *PathTreeNo | |||||||
| 
 | 
 | ||||||
| 	rawValue := os.Getenv(envName) | 	rawValue := os.Getenv(envName) | ||||||
| 
 | 
 | ||||||
|  | 	preferences := pathNode.Operation.Preferences.(*EnvOpPreferences) | ||||||
|  | 
 | ||||||
|  | 	var node *yaml.Node | ||||||
|  | 	if preferences.StringValue { | ||||||
|  | 		node = &yaml.Node{ | ||||||
|  | 			Kind:  yaml.ScalarNode, | ||||||
|  | 			Tag:   "!!str", | ||||||
|  | 			Value: rawValue, | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		var dataBucket yaml.Node | ||||||
|  | 		decoder := yaml.NewDecoder(strings.NewReader(rawValue)) | ||||||
|  | 		errorReading := decoder.Decode(&dataBucket) | ||||||
|  | 		if errorReading != nil { | ||||||
|  | 			return nil, errorReading | ||||||
|  | 		} | ||||||
|  | 		//first node is a doc | ||||||
|  | 		node = UnwrapDoc(&dataBucket) | ||||||
|  | 	} | ||||||
|  | 	log.Debug("ENV tag", node.Tag) | ||||||
|  | 	log.Debug("ENV value", node.Value) | ||||||
|  | 	log.Debug("ENV Kind", node.Kind) | ||||||
|  | 
 | ||||||
| 	target := &CandidateNode{ | 	target := &CandidateNode{ | ||||||
| 		Path:     make([]interface{}, 0), | 		Path:     make([]interface{}, 0), | ||||||
| 		Document: 0, | 		Document: 0, | ||||||
| 		Filename: "", | 		Filename: "", | ||||||
| 		Node: &yaml.Node{ | 		Node:     node, | ||||||
| 			Kind:  yaml.ScalarNode, |  | ||||||
| 			Tag:   "!!str", |  | ||||||
| 			Value: rawValue, |  | ||||||
| 		}, |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return nodeToMap(target), nil | 	return nodeToMap(target), nil | ||||||
|  | |||||||
| @ -5,20 +5,61 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var envOperatorScenarios = []expressionScenario{ | var envOperatorScenarios = []expressionScenario{ | ||||||
|  | 	{ | ||||||
|  | 		description:         "Read string environment variable", | ||||||
|  | 		environmentVariable: "cat meow", | ||||||
|  | 		expression:          `.a = env(myenv)`, | ||||||
|  | 		expected: []string{ | ||||||
|  | 			"D0, P[], ()::a: cat meow\n", | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		description:         "Read boolean environment variable", | ||||||
|  | 		environmentVariable: "true", | ||||||
|  | 		expression:          `.a = env(myenv)`, | ||||||
|  | 		expected: []string{ | ||||||
|  | 			"D0, P[], ()::a: true\n", | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		description:         "Read numeric environment variable", | ||||||
|  | 		environmentVariable: "12", | ||||||
|  | 		expression:          `.a = env(myenv)`, | ||||||
|  | 		expected: []string{ | ||||||
|  | 			"D0, P[], ()::a: 12\n", | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		description:         "Read yaml environment variable", | ||||||
|  | 		environmentVariable: "{b: fish}", | ||||||
|  | 		expression:          `.a = env(myenv)`, | ||||||
|  | 		expected: []string{ | ||||||
|  | 			"D0, P[], ()::a: {b: fish}\n", | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
| 	{ | 	{ | ||||||
| 		description:         "Read boolean environment variable as a string", | 		description:         "Read boolean environment variable as a string", | ||||||
| 		environmentVariable: "true", | 		environmentVariable: "true", | ||||||
| 		expression:          `strenv(myenv)`, | 		expression:          `.a = strenv(myenv)`, | ||||||
| 		expected: []string{ | 		expected: []string{ | ||||||
| 			"D0, P[], (!!str)::\"true\"\n", | 			"D0, P[], ()::a: \"true\"\n", | ||||||
| 		}, | 		}, | ||||||
| 	}, | 	}, | ||||||
| 	{ | 	{ | ||||||
| 		description:         "Read numeric environment variable as a string", | 		description:         "Read numeric environment variable as a string", | ||||||
| 		environmentVariable: "12", | 		environmentVariable: "12", | ||||||
| 		expression:          `strenv(myenv)`, | 		expression:          `.a = strenv(myenv)`, | ||||||
| 		expected: []string{ | 		expected: []string{ | ||||||
| 			"D0, P[], (!!str)::\"12\"\n", | 			"D0, P[], ()::a: \"12\"\n", | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		description:         "Dynamic key lookup with environment variable", | ||||||
|  | 		environmentVariable: "cat", | ||||||
|  | 		document:            `{cat: meow, dog: woof}`, | ||||||
|  | 		expression:          `.[env(myenv)]`, | ||||||
|  | 		expected: []string{ | ||||||
|  | 			"D0, P[cat], (!!str)::meow\n", | ||||||
| 		}, | 		}, | ||||||
| 	}, | 	}, | ||||||
| } | } | ||||||
|  | |||||||
| @ -54,6 +54,15 @@ var traversePathOperatorScenarios = []expressionScenario{ | |||||||
| 			"D0, P[{}], (!!str)::frog\n", | 			"D0, P[{}], (!!str)::frog\n", | ||||||
| 		}, | 		}, | ||||||
| 	}, | 	}, | ||||||
|  | 	{ | ||||||
|  | 		description:    "Dynamic keys", | ||||||
|  | 		subdescription: `Expressions within [] can be used to dynamically lookup / calculate keys`, | ||||||
|  | 		document:       `{b: apple, apple: crispy yum, banana: soft yum}`, | ||||||
|  | 		expression:     `.[.b]`, | ||||||
|  | 		expected: []string{ | ||||||
|  | 			"D0, P[apple], (!!str)::crispy yum\n", | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
| 	{ | 	{ | ||||||
| 		description:    "Children don't exist", | 		description:    "Children don't exist", | ||||||
| 		subdescription: "Nodes are added dynamically while traversing", | 		subdescription: "Nodes are added dynamically while traversing", | ||||||
|  | |||||||
| @ -17,7 +17,7 @@ import ( | |||||||
| type expressionScenario struct { | type expressionScenario struct { | ||||||
| 	description           string | 	description           string | ||||||
| 	subdescription        string | 	subdescription        string | ||||||
| 	environmentVariable	string | 	environmentVariable   string | ||||||
| 	document              string | 	document              string | ||||||
| 	document2             string | 	document2             string | ||||||
| 	expression            string | 	expression            string | ||||||
| @ -170,9 +170,10 @@ func documentInput(w *bufio.Writer, s expressionScenario) (string, string) { | |||||||
| 
 | 
 | ||||||
| 	envCommand := "" | 	envCommand := "" | ||||||
| 
 | 
 | ||||||
| 		if(s.environmentVariable != "") { | 	if s.environmentVariable != "" { | ||||||
| 			envCommand = fmt.Sprintf("myenv=\"%v\" ", s.environmentVariable) | 		envCommand = fmt.Sprintf("myenv=\"%v\" ", s.environmentVariable) | ||||||
| 		} | 		os.Setenv("myenv", s.environmentVariable) | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	if s.document != "" { | 	if s.document != "" { | ||||||
| 		if s.dontFormatInputForDoc { | 		if s.dontFormatInputForDoc { | ||||||
| @ -201,7 +202,6 @@ func documentInput(w *bufio.Writer, s expressionScenario) (string, string) { | |||||||
| 
 | 
 | ||||||
| 		writeOrPanic(w, "then\n") | 		writeOrPanic(w, "then\n") | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 		if s.expression != "" { | 		if s.expression != "" { | ||||||
| 			writeOrPanic(w, fmt.Sprintf("```bash\n%vyq %v '%v' %v\n```\n", envCommand, command, s.expression, files)) | 			writeOrPanic(w, fmt.Sprintf("```bash\n%vyq %v '%v' %v\n```\n", envCommand, command, s.expression, files)) | ||||||
| 		} else { | 		} else { | ||||||
|  | |||||||
| @ -181,17 +181,20 @@ func stringValue(wrapped bool) lex.Action { | |||||||
| func envOp(strenv bool) lex.Action { | func envOp(strenv bool) lex.Action { | ||||||
| 	return func(s *lex.Scanner, m *machines.Match) (interface{}, error) { | 	return func(s *lex.Scanner, m *machines.Match) (interface{}, error) { | ||||||
| 		value := string(m.Bytes) | 		value := string(m.Bytes) | ||||||
|  | 		preferences := &EnvOpPreferences{} | ||||||
| 
 | 
 | ||||||
| 		if strenv { | 		if strenv { | ||||||
| 			// strenv( ) | 			// strenv( ) | ||||||
| 			value = value[7:len(value)-1] | 			value = value[7 : len(value)-1] | ||||||
| 		 } else { | 			preferences.StringValue = true | ||||||
|  | 		} else { | ||||||
| 			//env( ) | 			//env( ) | ||||||
| 			value = value[4:len(value)-1] | 			value = value[4 : len(value)-1] | ||||||
| 		 } | 		} | ||||||
| 
 | 
 | ||||||
| 		envOperation := CreateValueOperation(value, value) | 		envOperation := CreateValueOperation(value, value) | ||||||
| 		envOperation.OperationType = EnvOp | 		envOperation.OperationType = EnvOp | ||||||
|  | 		envOperation.Preferences = preferences | ||||||
| 
 | 
 | ||||||
| 		return &Token{TokenType: OperationToken, Operation: envOperation}, nil | 		return &Token{TokenType: OperationToken, Operation: envOperation}, nil | ||||||
| 	} | 	} | ||||||
| @ -286,6 +289,7 @@ func initLexer() (*lex.Lexer, error) { | |||||||
| 
 | 
 | ||||||
| 	lexer.Add([]byte(`"[^"]*"`), stringValue(true)) | 	lexer.Add([]byte(`"[^"]*"`), stringValue(true)) | ||||||
| 	lexer.Add([]byte(`strenv\([^\)]+\)`), envOp(true)) | 	lexer.Add([]byte(`strenv\([^\)]+\)`), envOp(true)) | ||||||
|  | 	lexer.Add([]byte(`env\([^\)]+\)`), envOp(false)) | ||||||
| 
 | 
 | ||||||
| 	lexer.Add([]byte(`\[`), literalToken(OpenCollect, false)) | 	lexer.Add([]byte(`\[`), literalToken(OpenCollect, false)) | ||||||
| 	lexer.Add([]byte(`\]`), literalToken(CloseCollect, true)) | 	lexer.Add([]byte(`\]`), literalToken(CloseCollect, true)) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user