@@ -12,6 +12,7 @@ import (
12
12
"github.com/lima-vm/lima/pkg/limatmpl"
13
13
"github.com/lima-vm/lima/pkg/limayaml"
14
14
"github.com/lima-vm/lima/pkg/store/dirnames"
15
+ "github.com/lima-vm/lima/pkg/yqutil"
15
16
"github.com/sirupsen/logrus"
16
17
"github.com/spf13/cobra"
17
18
)
@@ -34,6 +35,7 @@ func newTemplateCommand() *cobra.Command {
34
35
templateCommand .AddCommand (
35
36
newTemplateCopyCommand (),
36
37
newTemplateValidateCommand (),
38
+ newTemplateYQCommand (),
37
39
)
38
40
return templateCommand
39
41
}
@@ -71,7 +73,24 @@ func newTemplateCopyCommand() *cobra.Command {
71
73
return templateCopyCommand
72
74
}
73
75
76
+ func fillDefaults (tmpl * limatmpl.Template ) error {
77
+ limaDir , err := dirnames .LimaDir ()
78
+ if err != nil {
79
+ return err
80
+ }
81
+ // Load() will merge the template with override.yaml and default.yaml via FillDefaults().
82
+ // FillDefaults() needs the potential instance directory to validate host templates using {{.Dir}}.
83
+ filePath := filepath .Join (limaDir , tmpl .Name + ".yaml" )
84
+ tmpl .Config , err = limayaml .Load (tmpl .Bytes , filePath )
85
+ if err == nil {
86
+ tmpl .Bytes , err = limayaml .Marshal (tmpl .Config , false )
87
+ }
88
+ return err
89
+ }
90
+
74
91
func templateCopyAction (cmd * cobra.Command , args []string ) error {
92
+ source := args [0 ]
93
+ target := args [1 ]
75
94
embed , err := cmd .Flags ().GetBool ("embed" )
76
95
if err != nil {
77
96
return err
@@ -97,12 +116,12 @@ func templateCopyAction(cmd *cobra.Command, args []string) error {
97
116
if embed && verbatim {
98
117
return errors .New ("--verbatim cannot be used with any of --embed, --embed-all, or --fill" )
99
118
}
100
- tmpl , err := limatmpl .Read (cmd .Context (), "" , args [ 0 ] )
119
+ tmpl , err := limatmpl .Read (cmd .Context (), "" , source )
101
120
if err != nil {
102
121
return err
103
122
}
104
123
if len (tmpl .Bytes ) == 0 {
105
- return fmt .Errorf ("don't know how to interpret %q as a template locator" , args [ 0 ] )
124
+ return fmt .Errorf ("don't know how to interpret %q as a template locator" , source )
106
125
}
107
126
if ! verbatim {
108
127
if embed {
@@ -117,24 +136,11 @@ func templateCopyAction(cmd *cobra.Command, args []string) error {
117
136
}
118
137
}
119
138
if fill {
120
- limaDir , err := dirnames .LimaDir ()
121
- if err != nil {
122
- return err
123
- }
124
- // Load() will merge the template with override.yaml and default.yaml via FillDefaults().
125
- // FillDefaults() needs the potential instance directory to validate host templates using {{.Dir}}.
126
- filePath := filepath .Join (limaDir , tmpl .Name + ".yaml" )
127
- tmpl .Config , err = limayaml .Load (tmpl .Bytes , filePath )
128
- if err != nil {
129
- return err
130
- }
131
- tmpl .Bytes , err = limayaml .Marshal (tmpl .Config , false )
132
- if err != nil {
139
+ if err := fillDefaults (tmpl ); err != nil {
133
140
return err
134
141
}
135
142
}
136
143
writer := cmd .OutOrStdout ()
137
- target := args [1 ]
138
144
if target != "-" {
139
145
file , err := os .OpenFile (target , os .O_WRONLY | os .O_CREATE | os .O_TRUNC , 0o644 )
140
146
if err != nil {
@@ -147,6 +153,51 @@ func templateCopyAction(cmd *cobra.Command, args []string) error {
147
153
return err
148
154
}
149
155
156
+ const templateYQHelp = `Use the builtin YQ evaluator to extract information from a template.
157
+ External references are embedded and default values are filled in
158
+ before the YQ expression is evaluated.
159
+
160
+ Example:
161
+ limactl template yq template://default '.images[].location'
162
+
163
+ The example command is equivalent to using an external yq command like this:
164
+ limactl template copy --fill template://default - | yq '.images[].location'
165
+ `
166
+
167
+ func newTemplateYQCommand () * cobra.Command {
168
+ templateYQCommand := & cobra.Command {
169
+ Use : "yq TEMPLATE EXPR" ,
170
+ Short : "Query template expressions" ,
171
+ Long : templateYQHelp ,
172
+ Args : WrapArgsError (cobra .ExactArgs (2 )),
173
+ RunE : templateYQAction ,
174
+ }
175
+ return templateYQCommand
176
+ }
177
+
178
+ func templateYQAction (cmd * cobra.Command , args []string ) error {
179
+ locator := args [0 ]
180
+ expr := args [1 ]
181
+ tmpl , err := limatmpl .Read (cmd .Context (), "" , locator )
182
+ if err != nil {
183
+ return err
184
+ }
185
+ if len (tmpl .Bytes ) == 0 {
186
+ return fmt .Errorf ("don't know how to interpret %q as a template locator" , locator )
187
+ }
188
+ if err := tmpl .Embed (cmd .Context (), true , true ); err != nil {
189
+ return err
190
+ }
191
+ if err := fillDefaults (tmpl ); err != nil {
192
+ return err
193
+ }
194
+ out , err := yqutil .EvaluateExpressionPlain (expr , string (tmpl .Bytes ))
195
+ if err == nil {
196
+ _ , err = fmt .Fprint (cmd .OutOrStdout (), out )
197
+ }
198
+ return err
199
+ }
200
+
150
201
func newTemplateValidateCommand () * cobra.Command {
151
202
templateValidateCommand := & cobra.Command {
152
203
Use : "validate TEMPLATE [TEMPLATE, ...]" ,
0 commit comments