Skip to content

Commit 04fe625

Browse files
authored
Image Customizer: Support string mountPoint (#10862)
1 parent 015c335 commit 04fe625

2 files changed

Lines changed: 50 additions & 3 deletions

File tree

toolkit/tools/imagecustomizer/docs/configuration.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,25 @@ The meaning of this value depends on the type property.
10101010

10111011
## mountPoint type
10121012

1013+
You can configure `mountPoint` in one of two ways:
1014+
1015+
1. **Structured Format**: Use `idType`, `options`, and `path` fields for a more detailed configuration.
1016+
1017+
```yaml
1018+
mountPoint:
1019+
path: /boot/efi
1020+
options: umask=0077
1021+
idType: part-uuid
1022+
```
1023+
1024+
2. **Shorthand Path Format**: Provide the mount path directly as a string when only `path` is required.
1025+
1026+
```yaml
1027+
mountPoint: /boot/efi
1028+
```
1029+
1030+
In this shorthand format, only the `path` is specified, and default values will be applied to any optional fields.
1031+
10131032
### idType [string]
10141033

10151034
Default: `part-uuid`

toolkit/tools/imagecustomizerapi/mountpoint.go

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
// Copyright (c) Microsoft Corporation.
2-
// Licensed under the MIT License.
3-
41
package imagecustomizerapi
52

63
import (
74
"fmt"
5+
6+
"github.com/microsoft/azurelinux/toolkit/tools/internal/sliceutils"
7+
"gopkg.in/yaml.v3"
88
)
99

1010
// MountPoint holds the mounting information for each partition.
@@ -17,6 +17,34 @@ type MountPoint struct {
1717
Path string `yaml:"path"`
1818
}
1919

20+
// UnmarshalYAML enables MountPoint to handle both a shorthand path and a structured object.
21+
func (p *MountPoint) UnmarshalYAML(value *yaml.Node) error {
22+
// Check if the node is a scalar (i.e., single path string).
23+
if value.Kind == yaml.ScalarNode {
24+
// Treat scalar value as the Path directly.
25+
p.Path = value.Value
26+
return nil
27+
}
28+
29+
// yaml.Node.Decode() doesn't respect the KnownFields() option.
30+
// So, manually enforce this.
31+
validFields := []string{"idType", "options", "path"}
32+
for i := 0; i < len(value.Content); i += 2 {
33+
key := value.Content[i].Value
34+
if !sliceutils.ContainsValue(validFields, key) {
35+
return fmt.Errorf("line %d: field %s not found in type %s", value.Line, key, "MountPoint")
36+
}
37+
}
38+
39+
// Otherwise, decode as a full MountPoint struct.
40+
type IntermediateTypeMountPoint MountPoint
41+
err := value.Decode((*IntermediateTypeMountPoint)(p))
42+
if err != nil {
43+
return fmt.Errorf("failed to parse MountPoint struct:\n%w", err)
44+
}
45+
return nil
46+
}
47+
2048
// IsValid returns an error if the MountPoint is not valid
2149
func (p *MountPoint) IsValid() error {
2250
err := p.IdType.IsValid()

0 commit comments

Comments
 (0)