@@ -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+
315346func resolveTestPassword (env * azldev.Env , options * ImageBootOptions ) error {
316347 if options .TestUserPasswordFile == "" {
317348 return nil
0 commit comments