@@ -12,6 +12,7 @@ import (
1212 "github.com/lima-vm/lima/pkg/limatmpl"
1313 "github.com/lima-vm/lima/pkg/limayaml"
1414 "github.com/lima-vm/lima/pkg/store/dirnames"
15+ "github.com/lima-vm/lima/pkg/yqutil"
1516 "github.com/sirupsen/logrus"
1617 "github.com/spf13/cobra"
1718)
@@ -34,6 +35,7 @@ func newTemplateCommand() *cobra.Command {
3435 templateCommand .AddCommand (
3536 newTemplateCopyCommand (),
3637 newTemplateValidateCommand (),
38+ newTemplateYQCommand (),
3739 )
3840 return templateCommand
3941}
@@ -71,7 +73,24 @@ func newTemplateCopyCommand() *cobra.Command {
7173 return templateCopyCommand
7274}
7375
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+
7491func templateCopyAction (cmd * cobra.Command , args []string ) error {
92+ source := args [0 ]
93+ target := args [1 ]
7594 embed , err := cmd .Flags ().GetBool ("embed" )
7695 if err != nil {
7796 return err
@@ -97,12 +116,12 @@ func templateCopyAction(cmd *cobra.Command, args []string) error {
97116 if embed && verbatim {
98117 return errors .New ("--verbatim cannot be used with any of --embed, --embed-all, or --fill" )
99118 }
100- tmpl , err := limatmpl .Read (cmd .Context (), "" , args [ 0 ] )
119+ tmpl , err := limatmpl .Read (cmd .Context (), "" , source )
101120 if err != nil {
102121 return err
103122 }
104123 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 )
106125 }
107126 if ! verbatim {
108127 if embed {
@@ -117,24 +136,11 @@ func templateCopyAction(cmd *cobra.Command, args []string) error {
117136 }
118137 }
119138 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 {
133140 return err
134141 }
135142 }
136143 writer := cmd .OutOrStdout ()
137- target := args [1 ]
138144 if target != "-" {
139145 file , err := os .OpenFile (target , os .O_WRONLY | os .O_CREATE | os .O_TRUNC , 0o644 )
140146 if err != nil {
@@ -147,6 +153,51 @@ func templateCopyAction(cmd *cobra.Command, args []string) error {
147153 return err
148154}
149155
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+
150201func newTemplateValidateCommand () * cobra.Command {
151202 templateValidateCommand := & cobra.Command {
152203 Use : "validate TEMPLATE [TEMPLATE, ...]" ,
0 commit comments