Skip to content

Commit d8dde5c

Browse files
committed
fix: updates
1 parent e686239 commit d8dde5c

File tree

2 files changed

+93
-5
lines changed

2 files changed

+93
-5
lines changed

internal/app/azldev/cmds/image/boot.go

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,12 @@ Requirements:
191191
options.ImageName = args[0]
192192
}
193193

194-
diskSizeExplicit := cmd.Flags().Lookup("disk-size").Changed
194+
explicit := bootFlagsExplicit{
195+
DiskSize: cmd.Flags().Lookup("disk-size").Changed,
196+
TestUser: cmd.Flags().Lookup("test-user").Changed,
197+
}
195198

196-
return nil, bootImage(env, options, diskSizeExplicit)
199+
return nil, bootImage(env, options, explicit)
197200
})
198201

199202
cmd.Flags().StringVarP(&options.ImagePath, "image-path", "i", "",
@@ -250,18 +253,36 @@ func addBootFlags(cmd *cobra.Command, options *ImageBootOptions) {
250253
cmd.MarkFlagsMutuallyExclusive("image-path", "format")
251254
}
252255

253-
func bootImage(env *azldev.Env, options *ImageBootOptions, diskSizeExplicit bool) error {
256+
// bootFlagsExplicit tracks which flags were explicitly set on the command line
257+
// (vs. left at their default). Used to distinguish "user said nothing" from
258+
// "user said the default".
259+
type bootFlagsExplicit struct {
260+
DiskSize bool
261+
TestUser bool
262+
}
263+
264+
func bootImage(env *azldev.Env, options *ImageBootOptions, explicit bootFlagsExplicit) error {
254265
needEmptyDisk := options.ISOPath != "" && options.ImagePath == "" && options.ImageName == ""
255266

256-
if err := validateBootOptions(options, diskSizeExplicit, needEmptyDisk); err != nil {
267+
if err := validateBootOptions(options, explicit.DiskSize, needEmptyDisk); err != nil {
257268
return err
258269
}
259270

260271
if err := resolveTestPassword(env, options); err != nil {
261272
return err
262273
}
263274

264-
needCloudInit := options.TestUserPassword != "" || options.AuthorizedPublicKeyPath != ""
275+
// Cloud-init is needed whenever the user asked for any user-provisioning behavior:
276+
// credentials (password / SSH key) OR an explicit '--test-user' (which signals
277+
// they want the named account created even if no auth is supplied — otherwise
278+
// '--test-user' would be silently ignored).
279+
needCloudInit := shouldBuildCloudInit(options, explicit.TestUser)
280+
281+
hasLoginCredential := options.TestUserPassword != "" || options.AuthorizedPublicKeyPath != ""
282+
if !hasLoginCredential {
283+
slog.Warn("No test password ('--test-password'/'--test-password-file') or SSH key " +
284+
"('--authorized-public-key') supplied; you may have no way to log in to the booted OS")
285+
}
265286

266287
if err := verifyISOExists(env, options.ISOPath); err != nil {
267288
return err
@@ -312,6 +333,16 @@ func validateBootOptions(options *ImageBootOptions, diskSizeExplicit, needEmptyD
312333
return nil
313334
}
314335

336+
// shouldBuildCloudInit reports whether a cloud-init NoCloud seed ISO should be
337+
// generated and attached. It returns true when the user supplied any
338+
// user-provisioning intent: credentials (password or SSH key) OR an explicit
339+
// '--test-user' (otherwise '--test-user' would be silently ignored).
340+
func shouldBuildCloudInit(options *ImageBootOptions, testUserExplicit bool) bool {
341+
return options.TestUserPassword != "" ||
342+
options.AuthorizedPublicKeyPath != "" ||
343+
testUserExplicit
344+
}
345+
315346
func resolveTestPassword(env *azldev.Env, options *ImageBootOptions) error {
316347
if options.TestUserPasswordFile == "" {
317348
return nil
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
package image
5+
6+
import (
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestShouldBuildCloudInit(t *testing.T) {
13+
tests := []struct {
14+
name string
15+
options ImageBootOptions
16+
testUserExplicit bool
17+
want bool
18+
}{
19+
{
20+
name: "no credentials and no explicit test-user => false",
21+
options: ImageBootOptions{},
22+
testUserExplicit: false,
23+
want: false,
24+
},
25+
{
26+
name: "explicit '--test-user' alone => true (avoid silent ignore)",
27+
options: ImageBootOptions{TestUserName: "foo"},
28+
testUserExplicit: true,
29+
want: true,
30+
},
31+
{
32+
name: "default test-user value but flag not changed => false",
33+
options: ImageBootOptions{TestUserName: "test"},
34+
testUserExplicit: false,
35+
want: false,
36+
},
37+
{
38+
name: "password supplied => true",
39+
options: ImageBootOptions{TestUserPassword: "pw"},
40+
testUserExplicit: false,
41+
want: true,
42+
},
43+
{
44+
name: "authorized public key supplied => true",
45+
options: ImageBootOptions{AuthorizedPublicKeyPath: "/some/key.pub"},
46+
testUserExplicit: false,
47+
want: true,
48+
},
49+
}
50+
51+
for _, tc := range tests {
52+
t.Run(tc.name, func(t *testing.T) {
53+
got := shouldBuildCloudInit(&tc.options, tc.testUserExplicit)
54+
assert.Equal(t, tc.want, got)
55+
})
56+
}
57+
}

0 commit comments

Comments
 (0)