Skip to content

Commit f1babc0

Browse files
authored
Merge pull request #2271 from afbjorklund/cloud-config
Generate cloud-config outside of cidata.iso too
2 parents c6b5b31 + 4b3a0fa commit f1babc0

File tree

11 files changed

+140
-26
lines changed

11 files changed

+140
-26
lines changed

.yamllint

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
extends: default
44

5+
ignore: |
6+
# this is a yaml template, needs to be executed
7+
pkg/cidata/cloud-config.yaml
8+
59
rules:
610
indentation:
711
indent-sequences: false

cmd/limactl/factory-reset.go

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"path/filepath"
77
"strings"
88

9+
"github.com/lima-vm/lima/pkg/cidata"
910
"github.com/lima-vm/lima/pkg/instance"
1011
"github.com/lima-vm/lima/pkg/store"
1112
"github.com/lima-vm/lima/pkg/store/filenames"
@@ -63,6 +64,11 @@ func factoryResetAction(_ *cobra.Command, args []string) error {
6364
}
6465
}
6566
}
67+
// Regenerate the cloud-config.yaml, to reflect any changes to the global _config
68+
if err := cidata.GenerateCloudConfig(inst.Dir, instName, inst.Config); err != nil {
69+
logrus.Error(err)
70+
}
71+
6672
logrus.Infof("Instance %q has been factory reset", instName)
6773
return nil
6874
}

pkg/cidata/cidata.TEMPLATE.d/user-data

+6
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ users:
3939
- {{ printf "%q" $val }}
4040
{{- end }}
4141

42+
{{- if .BootScripts }}
4243
write_files:
4344
- content: |
4445
#!/bin/sh
@@ -52,6 +53,7 @@ write_files:
5253
owner: root:root
5354
path: /var/lib/cloud/scripts/per-boot/00-lima.boot.sh
5455
permissions: '0755'
56+
{{- end }}
5557

5658
{{- if .DNSAddresses }}
5759
# This has no effect on systems using systemd-resolved, but is used
@@ -66,16 +68,20 @@ resolv_conf:
6668
{{- end }}
6769
{{- end }}
6870

71+
{{- if or .CACerts.RemoveDefaults .CACerts.Trusted }}
6972
{{ with .CACerts }}
7073
ca_certs:
74+
{{- if .RemoveDefaults }}
7175
remove_defaults: {{ .RemoveDefaults }}
76+
{{- end }}
7277
{{- if .Trusted}}
7378
trusted:
7479
{{- range $cert := .Trusted }}
7580
- |
7681
{{- range $line := $cert.Lines }}
7782
{{ $line }}
7883
{{- end }}
84+
{{- end }}
7985
{{- end }}
8086
{{- end }}
8187
{{- end }}

pkg/cidata/cidata.go

+56-17
Original file line numberDiff line numberDiff line change
@@ -111,19 +111,20 @@ func setupEnv(instConfigEnv map[string]string, propagateProxyEnv bool, slirpGate
111111
return env, nil
112112
}
113113

114-
func GenerateISO9660(instDir, name string, instConfig *limayaml.LimaYAML, udpDNSLocalPort, tcpDNSLocalPort int, nerdctlArchive string, vsockPort int, virtioPort string) error {
114+
func templateArgs(bootScripts bool, instDir, name string, instConfig *limayaml.LimaYAML, udpDNSLocalPort, tcpDNSLocalPort, vsockPort int, virtioPort string) (*TemplateArgs, error) {
115115
if err := limayaml.Validate(instConfig, false); err != nil {
116-
return err
116+
return nil, err
117117
}
118118
u, err := osutil.LimaUser(true)
119119
if err != nil {
120-
return err
120+
return nil, err
121121
}
122122
uid, err := strconv.Atoi(u.Uid)
123123
if err != nil {
124-
return err
124+
return nil, err
125125
}
126126
args := TemplateArgs{
127+
BootScripts: bootScripts,
127128
Name: name,
128129
User: u.Username,
129130
UID: uid,
@@ -150,14 +151,14 @@ func GenerateISO9660(instDir, name string, instConfig *limayaml.LimaYAML, udpDNS
150151
usernetName := instConfig.Networks[firstUsernetIndex].Lima
151152
subnet, err = usernet.Subnet(usernetName)
152153
if err != nil {
153-
return err
154+
return nil, err
154155
}
155156
args.SlirpGateway = usernet.GatewayIP(subnet)
156157
args.SlirpDNS = usernet.GatewayIP(subnet)
157158
} else {
158159
subnet, _, err = net.ParseCIDR(networks.SlirpNetwork)
159160
if err != nil {
160-
return err
161+
return nil, err
161162
}
162163
args.SlirpGateway = usernet.GatewayIP(subnet)
163164
if *instConfig.VMType == limayaml.VZ {
@@ -173,10 +174,10 @@ func GenerateISO9660(instDir, name string, instConfig *limayaml.LimaYAML, udpDNS
173174

174175
pubKeys, err := sshutil.DefaultPubKeys(*instConfig.SSH.LoadDotSSHPubKeys)
175176
if err != nil {
176-
return err
177+
return nil, err
177178
}
178179
if len(pubKeys) == 0 {
179-
return errors.New("no SSH key was found, run `ssh-keygen`")
180+
return nil, errors.New("no SSH key was found, run `ssh-keygen`")
180181
}
181182
for _, f := range pubKeys {
182183
args.SSHPubKeys = append(args.SSHPubKeys, f.Content)
@@ -193,17 +194,17 @@ func GenerateISO9660(instDir, name string, instConfig *limayaml.LimaYAML, udpDNS
193194
}
194195
hostHome, err := localpathutil.Expand("~")
195196
if err != nil {
196-
return err
197+
return nil, err
197198
}
198199
for i, f := range instConfig.Mounts {
199200
tag := fmt.Sprintf("mount%d", i)
200201
location, err := localpathutil.Expand(f.Location)
201202
if err != nil {
202-
return err
203+
return nil, err
203204
}
204205
mountPoint, err := localpathutil.Expand(f.MountPoint)
205206
if err != nil {
206-
return err
207+
return nil, err
207208
}
208209
options := "defaults"
209210
switch fstype {
@@ -217,7 +218,7 @@ func GenerateISO9660(instDir, name string, instConfig *limayaml.LimaYAML, udpDNS
217218
options += fmt.Sprintf(",version=%s", *f.NineP.ProtocolVersion)
218219
msize, err := units.RAMInBytes(*f.NineP.Msize)
219220
if err != nil {
220-
return fmt.Errorf("failed to parse msize for %q: %w", location, err)
221+
return nil, fmt.Errorf("failed to parse msize for %q: %w", location, err)
221222
}
222223
options += fmt.Sprintf(",msize=%d", msize)
223224
options += fmt.Sprintf(",cache=%s", *f.NineP.Cache)
@@ -268,7 +269,7 @@ func GenerateISO9660(instDir, name string, instConfig *limayaml.LimaYAML, udpDNS
268269

269270
args.Env, err = setupEnv(instConfig.Env, *instConfig.PropagateProxyEnv, args.SlirpGateway)
270271
if err != nil {
271-
return err
272+
return nil, err
272273
}
273274

274275
switch {
@@ -285,7 +286,7 @@ func GenerateISO9660(instDir, name string, instConfig *limayaml.LimaYAML, udpDNS
285286
default:
286287
args.DNSAddresses, err = osutil.DNSAddresses()
287288
if err != nil {
288-
return err
289+
return nil, err
289290
}
290291
}
291292

@@ -294,12 +295,12 @@ func GenerateISO9660(instDir, name string, instConfig *limayaml.LimaYAML, udpDNS
294295
for _, path := range instConfig.CACertificates.Files {
295296
expanded, err := localpathutil.Expand(path)
296297
if err != nil {
297-
return err
298+
return nil, err
298299
}
299300

300301
content, err := os.ReadFile(expanded)
301302
if err != nil {
302-
return err
303+
return nil, err
303304
}
304305

305306
cert := getCert(string(content))
@@ -311,6 +312,12 @@ func GenerateISO9660(instDir, name string, instConfig *limayaml.LimaYAML, udpDNS
311312
args.CACerts.Trusted = append(args.CACerts.Trusted, cert)
312313
}
313314

315+
// Remove empty caCerts (default values) from configuration yaml
316+
if !*args.CACerts.RemoveDefaults && len(args.CACerts.Trusted) == 0 {
317+
args.CACerts.RemoveDefaults = nil
318+
args.CACerts.Trusted = nil
319+
}
320+
314321
args.BootCmds = getBootCmds(instConfig.Provision)
315322

316323
for _, f := range instConfig.Provision {
@@ -319,11 +326,43 @@ func GenerateISO9660(instDir, name string, instConfig *limayaml.LimaYAML, udpDNS
319326
}
320327
}
321328

329+
return &args, nil
330+
}
331+
332+
func GenerateCloudConfig(instDir, name string, instConfig *limayaml.LimaYAML) error {
333+
args, err := templateArgs(false, instDir, name, instConfig, 0, 0, 0, "")
334+
if err != nil {
335+
return err
336+
}
337+
// mounts are not included here
338+
args.Mounts = nil
339+
// resolv_conf is not included here
340+
args.DNSAddresses = nil
341+
342+
if err := ValidateTemplateArgs(args); err != nil {
343+
return err
344+
}
345+
346+
config, err := ExecuteTemplateCloudConfig(args)
347+
if err != nil {
348+
return err
349+
}
350+
351+
os.RemoveAll(filepath.Join(instDir, filenames.CloudConfig)) // delete existing
352+
return os.WriteFile(filepath.Join(instDir, filenames.CloudConfig), config, 0o444)
353+
}
354+
355+
func GenerateISO9660(instDir, name string, instConfig *limayaml.LimaYAML, udpDNSLocalPort, tcpDNSLocalPort int, nerdctlArchive string, vsockPort int, virtioPort string) error {
356+
args, err := templateArgs(true, instDir, name, instConfig, udpDNSLocalPort, tcpDNSLocalPort, vsockPort, virtioPort)
357+
if err != nil {
358+
return err
359+
}
360+
322361
if err := ValidateTemplateArgs(args); err != nil {
323362
return err
324363
}
325364

326-
layout, err := ExecuteTemplate(args)
365+
layout, err := ExecuteTemplateCIDataISO(args)
327366
if err != nil {
328367
return err
329368
}

pkg/cidata/cloud-config.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cidata.TEMPLATE.d/user-data

pkg/cidata/template.go

+17-5
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ type TemplateArgs struct {
7575
TCPDNSLocalPort int
7676
Env map[string]string
7777
Param map[string]string
78+
BootScripts bool
7879
DNSAddresses []string
7980
CACerts CACerts
8081
HostHomeMountPoint string
@@ -89,7 +90,7 @@ type TemplateArgs struct {
8990
TimeZone string
9091
}
9192

92-
func ValidateTemplateArgs(args TemplateArgs) error {
93+
func ValidateTemplateArgs(args *TemplateArgs) error {
9394
if err := identifiers.Validate(args.Name); err != nil {
9495
return err
9596
}
@@ -114,13 +115,24 @@ func ValidateTemplateArgs(args TemplateArgs) error {
114115
return fmt.Errorf("field mounts[%d] must be absolute, got %q", i, f)
115116
}
116117
}
117-
if args.CACerts.RemoveDefaults == nil {
118-
return errors.New("field CACerts.RemoveDefaults must be set")
119-
}
120118
return nil
121119
}
122120

123-
func ExecuteTemplate(args TemplateArgs) ([]iso9660util.Entry, error) {
121+
func ExecuteTemplateCloudConfig(args *TemplateArgs) ([]byte, error) {
122+
if err := ValidateTemplateArgs(args); err != nil {
123+
return nil, err
124+
}
125+
126+
userData, err := templateFS.ReadFile(path.Join(templateFSRoot, "user-data"))
127+
if err != nil {
128+
return nil, err
129+
}
130+
131+
cloudConfigYaml := string(userData)
132+
return textutil.ExecuteTemplate(cloudConfigYaml, args)
133+
}
134+
135+
func ExecuteTemplateCIDataISO(args *TemplateArgs) ([]iso9660util.Entry, error) {
124136
if err := ValidateTemplateArgs(args); err != nil {
125137
return nil, err
126138
}

pkg/cidata/template_test.go

+41-4
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,45 @@ import (
1010

1111
var defaultRemoveDefaults = false
1212

13+
func TestConfig(t *testing.T) {
14+
args := &TemplateArgs{
15+
Name: "default",
16+
User: "foo",
17+
UID: 501,
18+
Home: "/home/foo.linux",
19+
SSHPubKeys: []string{
20+
"ssh-rsa dummy [email protected]",
21+
},
22+
MountType: "reverse-sshfs",
23+
}
24+
config, err := ExecuteTemplateCloudConfig(args)
25+
assert.NilError(t, err)
26+
t.Log(string(config))
27+
assert.Assert(t, !strings.Contains(string(config), "ca_certs:"))
28+
}
29+
30+
func TestConfigCACerts(t *testing.T) {
31+
args := &TemplateArgs{
32+
Name: "default",
33+
User: "foo",
34+
UID: 501,
35+
Home: "/home/foo.linux",
36+
SSHPubKeys: []string{
37+
"ssh-rsa dummy [email protected]",
38+
},
39+
MountType: "reverse-sshfs",
40+
CACerts: CACerts{
41+
RemoveDefaults: &defaultRemoveDefaults,
42+
},
43+
}
44+
config, err := ExecuteTemplateCloudConfig(args)
45+
assert.NilError(t, err)
46+
t.Log(string(config))
47+
assert.Assert(t, strings.Contains(string(config), "ca_certs:"))
48+
}
49+
1350
func TestTemplate(t *testing.T) {
14-
args := TemplateArgs{
51+
args := &TemplateArgs{
1552
Name: "default",
1653
User: "foo",
1754
UID: 501,
@@ -29,7 +66,7 @@ func TestTemplate(t *testing.T) {
2966
Trusted: []Cert{},
3067
},
3168
}
32-
layout, err := ExecuteTemplate(args)
69+
layout, err := ExecuteTemplateCIDataISO(args)
3370
assert.NilError(t, err)
3471
for _, f := range layout {
3572
t.Logf("=== %q ===", f.Path)
@@ -46,7 +83,7 @@ func TestTemplate(t *testing.T) {
4683
}
4784

4885
func TestTemplate9p(t *testing.T) {
49-
args := TemplateArgs{
86+
args := &TemplateArgs{
5087
Name: "default",
5188
User: "foo",
5289
UID: 501,
@@ -63,7 +100,7 @@ func TestTemplate9p(t *testing.T) {
63100
RemoveDefaults: &defaultRemoveDefaults,
64101
},
65102
}
66-
layout, err := ExecuteTemplate(args)
103+
layout, err := ExecuteTemplateCIDataISO(args)
67104
assert.NilError(t, err)
68105
for _, f := range layout {
69106
t.Logf("=== %q ===", f.Path)

pkg/hostagent/hostagent.go

+3
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ func New(instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt
133133
virtioPort = "" // filenames.VirtioPort
134134
}
135135

136+
if err := cidata.GenerateCloudConfig(inst.Dir, instName, inst.Config); err != nil {
137+
return nil, err
138+
}
136139
if err := cidata.GenerateISO9660(inst.Dir, instName, inst.Config, udpDNSLocalPort, tcpDNSLocalPort, o.nerdctlArchive, vSockPort, virtioPort); err != nil {
137140
return nil, err
138141
}

pkg/instance/create.go

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"os"
88
"path/filepath"
99

10+
"github.com/lima-vm/lima/pkg/cidata"
1011
"github.com/lima-vm/lima/pkg/driver"
1112
"github.com/lima-vm/lima/pkg/driverutil"
1213
"github.com/lima-vm/lima/pkg/limayaml"
@@ -60,6 +61,9 @@ func Create(ctx context.Context, instName string, instConfig []byte, saveBrokenY
6061
if err := os.WriteFile(filePath, instConfig, 0o644); err != nil {
6162
return nil, err
6263
}
64+
if err := cidata.GenerateCloudConfig(instDir, instName, loadedInstConfig); err != nil {
65+
return nil, err
66+
}
6367
if err := os.WriteFile(filepath.Join(instDir, filenames.LimaVersion), []byte(version.Version), 0o444); err != nil {
6468
return nil, err
6569
}

0 commit comments

Comments
 (0)