From 466bb57f38534ec4a60d9d5391b9717aaf9720c6 Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Wed, 11 Dec 2024 17:50:52 +0000 Subject: [PATCH 01/23] progress --- .../imagecustomizerapi/additionalfile.go | 10 +- toolkit/tools/imagecustomizerapi/config.go | 12 +- toolkit/tools/imagecustomizerapi/dirconfig.go | 12 +- toolkit/tools/imagecustomizerapi/disk.go | 6 +- .../tools/imagecustomizerapi/filesystem.go | 6 +- toolkit/tools/imagecustomizerapi/iso.go | 4 +- .../imagecustomizerapi/kernelcommandline.go | 2 +- toolkit/tools/imagecustomizerapi/module.go | 6 +- .../tools/imagecustomizerapi/mountpoint.go | 6 +- toolkit/tools/imagecustomizerapi/os.go | 31 ++- toolkit/tools/imagecustomizerapi/overlay.go | 14 +- .../tools/imagecustomizerapi/packagelist.go | 2 +- toolkit/tools/imagecustomizerapi/packages.go | 14 +- toolkit/tools/imagecustomizerapi/partition.go | 12 +- toolkit/tools/imagecustomizerapi/password.go | 4 +- toolkit/tools/imagecustomizerapi/pxe.go | 4 +- toolkit/tools/imagecustomizerapi/script.go | 14 +- toolkit/tools/imagecustomizerapi/scripts.go | 4 +- toolkit/tools/imagecustomizerapi/selinux.go | 2 +- toolkit/tools/imagecustomizerapi/service.go | 4 +- toolkit/tools/imagecustomizerapi/storage.go | 10 +- toolkit/tools/imagecustomizerapi/user.go | 20 +- toolkit/tools/imagecustomizerapi/verity.go | 14 +- .../pkg/imagecustomizerlib/customizeos.go | 7 + .../pkg/imagecustomizerlib/imagehistory.go | 248 ++++++++++++++++++ 25 files changed, 368 insertions(+), 100 deletions(-) create mode 100644 toolkit/tools/pkg/imagecustomizerlib/imagehistory.go diff --git a/toolkit/tools/imagecustomizerapi/additionalfile.go b/toolkit/tools/imagecustomizerapi/additionalfile.go index 72c6145de5..bb0779ec5b 100644 --- a/toolkit/tools/imagecustomizerapi/additionalfile.go +++ b/toolkit/tools/imagecustomizerapi/additionalfile.go @@ -11,18 +11,20 @@ type AdditionalFileList []AdditionalFile type AdditionalFile struct { // The destination file path in the target OS that the file will be copied to. - Destination string `yaml:"destination"` + Destination string `yaml:"destination" json:"destination,omitempty"` // The source file path of the file that will copied. // Mutally exclusive with 'contents'. - Source string `yaml:"source"` + Source string `yaml:"source" json:"source,omitempty"` // A string that will be used as the contents of the file. // Mutally exclusive with 'source'. - Content *string `yaml:"content"` + Content *string `yaml:"content" json:"content,omitempty"` // The file permissions to set on the file. - Permissions *FilePermissions `yaml:"permissions"` + Permissions *FilePermissions `yaml:"permissions" json:"permissions,omitempty"` + + SHA256Hash string `yaml:"sha256hash" json:"sha256hash,omitempty"` } func (l AdditionalFileList) IsValid() (err error) { diff --git a/toolkit/tools/imagecustomizerapi/config.go b/toolkit/tools/imagecustomizerapi/config.go index 5238b0e952..4f95ca7eb2 100644 --- a/toolkit/tools/imagecustomizerapi/config.go +++ b/toolkit/tools/imagecustomizerapi/config.go @@ -10,12 +10,12 @@ import ( ) type Config struct { - Storage Storage `yaml:"storage"` - Iso *Iso `yaml:"iso"` - Pxe *Pxe `yaml:"pxe"` - OS *OS `yaml:"os"` - Scripts Scripts `yaml:"scripts"` - PreviewFeatures []string `yaml:"previewFeatures"` + Storage Storage `yaml:"storage" json:"storage,omitempty"` + Iso *Iso `yaml:"iso" json:"iso,omitempty"` + Pxe *Pxe `yaml:"pxe" json:"pxe,omitempty"` + OS *OS `yaml:"os" json:"os,omitempty"` + Scripts Scripts `yaml:"scripts" json:"scripts,omitempty"` + PreviewFeatures []string `yaml:"previewFeatures json:"previewFeatures,omitempty"` } func (c *Config) IsValid() (err error) { diff --git a/toolkit/tools/imagecustomizerapi/dirconfig.go b/toolkit/tools/imagecustomizerapi/dirconfig.go index e11be86e0c..ac76f8110a 100644 --- a/toolkit/tools/imagecustomizerapi/dirconfig.go +++ b/toolkit/tools/imagecustomizerapi/dirconfig.go @@ -13,22 +13,24 @@ type DirConfigList []DirConfig type DirConfig struct { // The path to the source directory that will be copied (can be relative or absolute path). - Source string `yaml:"source"` + Source string `yaml:"source" json:"source,omitempty"` // The absolute path in the target OS that the directory will be copied to. - Destination string `yaml:"destination"` + Destination string `yaml:"destination" json:"destination,omitempty"` // The permissions to set on all of the new directories being created on the target OS (including the top-level directory). // Note: If this value is not specified in the config, the permissions for these directories will be set to 0755. - NewDirPermissions *FilePermissions `yaml:"newDirPermissions"` + NewDirPermissions *FilePermissions `yaml:"newDirPermissions" json:"newDirPermissions,omitempty"` // The permissions to set on the directories being copied that already do exist on the target OS (including the top-level directory). // Note: If this value is not specified in the config, the permissions for this field will be the same as that of the pre-existing directory. - MergedDirPermissions *FilePermissions `yaml:"mergedDirPermissions"` + MergedDirPermissions *FilePermissions `yaml:"mergedDirPermissions" json:"mergedDirPermissions,omitempty"` // The permissions to set on the children file of the directory. // Note: If this value is not specified in the config, the permissions for these directories will be set to 0755. - ChildFilePermissions *FilePermissions `yaml:"childFilePermissions"` + ChildFilePermissions *FilePermissions `yaml:"childFilePermissions" json:"childFilePermissions,omitempty"` + + SHA256HashMap map[string]string `yaml:"sha256hashmap" json:"sha256hashmap,omitempty"` } func (l *DirConfigList) IsValid() (err error) { diff --git a/toolkit/tools/imagecustomizerapi/disk.go b/toolkit/tools/imagecustomizerapi/disk.go index 97bd7e3699..c9c8897b9f 100644 --- a/toolkit/tools/imagecustomizerapi/disk.go +++ b/toolkit/tools/imagecustomizerapi/disk.go @@ -26,14 +26,14 @@ const ( type Disk struct { // The type of partition table to use (e.g. mbr, gpt) - PartitionTableType PartitionTableType `yaml:"partitionTableType"` + PartitionTableType PartitionTableType `yaml:"partitionTableType" json:"partitionTableType,omitempty"` // The virtual size of the disk. // Note: This value is filled in by IsValid(). - MaxSize *DiskSize `yaml:"maxSize"` + MaxSize *DiskSize `yaml:"maxSize" json:"maxSize,omitempty"` // The partitions to allocate on the disk. - Partitions []Partition `yaml:"partitions"` + Partitions []Partition `yaml:"partitions" json:"partitions,omitempty"` } func (d *Disk) IsValid() error { diff --git a/toolkit/tools/imagecustomizerapi/filesystem.go b/toolkit/tools/imagecustomizerapi/filesystem.go index 4be08baf23..894ddd3599 100644 --- a/toolkit/tools/imagecustomizerapi/filesystem.go +++ b/toolkit/tools/imagecustomizerapi/filesystem.go @@ -10,11 +10,11 @@ import ( // FileSystem holds the file system information for a partition. type FileSystem struct { // DeviceId is the ID of the source partition. - DeviceId string `yaml:"deviceId"` + DeviceId string `yaml:"deviceId" json:"deviceId,omitempty"` // FileSystemType is the type of file system to use on the partition. - Type FileSystemType `yaml:"type"` + Type FileSystemType `yaml:"type" json:"type,omitempty"` // MountPoint contains the mount settings. - MountPoint *MountPoint `yaml:"mountPoint"` + MountPoint *MountPoint `yaml:"mountPoint" json:"mountPoint,omitempty"` // If 'DeviceId' points at a verity device, this value is the 'Id' of the data partition. // Otherwise, it is the same as 'DeviceId'. diff --git a/toolkit/tools/imagecustomizerapi/iso.go b/toolkit/tools/imagecustomizerapi/iso.go index 295f2af786..eeb2b95906 100644 --- a/toolkit/tools/imagecustomizerapi/iso.go +++ b/toolkit/tools/imagecustomizerapi/iso.go @@ -9,8 +9,8 @@ import ( // Iso defines how the generated iso media should be configured. type Iso struct { - KernelCommandLine KernelCommandLine `yaml:"kernelCommandLine"` - AdditionalFiles AdditionalFileList `yaml:"additionalFiles"` + KernelCommandLine KernelCommandLine `yaml:"kernelCommandLine" json:"kernelCommandLine,omitempty"` + AdditionalFiles AdditionalFileList `yaml:"additionalFiles" json:"additionalFiles,omitempty"` } func (i *Iso) IsValid() error { diff --git a/toolkit/tools/imagecustomizerapi/kernelcommandline.go b/toolkit/tools/imagecustomizerapi/kernelcommandline.go index bea59339a7..e413956fa9 100644 --- a/toolkit/tools/imagecustomizerapi/kernelcommandline.go +++ b/toolkit/tools/imagecustomizerapi/kernelcommandline.go @@ -9,7 +9,7 @@ import ( type KernelCommandLine struct { // Extra kernel command line args. - ExtraCommandLine []string `yaml:"extraCommandLine"` + ExtraCommandLine []string `yaml:"extraCommandLine" json:"extraCommandLine,omitempty"` } func (k *KernelCommandLine) IsValid() error { diff --git a/toolkit/tools/imagecustomizerapi/module.go b/toolkit/tools/imagecustomizerapi/module.go index 20a102145e..7f5ef82609 100644 --- a/toolkit/tools/imagecustomizerapi/module.go +++ b/toolkit/tools/imagecustomizerapi/module.go @@ -9,9 +9,9 @@ import ( ) type Module struct { - Name string `yaml:"name"` - LoadMode ModuleLoadMode `yaml:"loadMode"` - Options map[string]string `yaml:"options"` + Name string `yaml:"name" json:"name,omitempty"` + LoadMode ModuleLoadMode `yaml:"loadMode" json:"loadMode,omitempty"` + Options map[string]string `yaml:"options" json:"options,omitempty"` } type ModuleList []Module diff --git a/toolkit/tools/imagecustomizerapi/mountpoint.go b/toolkit/tools/imagecustomizerapi/mountpoint.go index 505dcccda3..8e6c650ffd 100644 --- a/toolkit/tools/imagecustomizerapi/mountpoint.go +++ b/toolkit/tools/imagecustomizerapi/mountpoint.go @@ -10,11 +10,11 @@ import ( // MountPoint holds the mounting information for each partition. type MountPoint struct { // The ID type to use for the source in the /etc/fstab file. - IdType MountIdentifierType `yaml:"idType"` + IdType MountIdentifierType `yaml:"idType" json:"idType,omitempty"` // The additional options for the mount. - Options string `yaml:"options"` + Options string `yaml:"options" json:"options,omitempty"` // The target directory path of the mount. - Path string `yaml:"path"` + Path string `yaml:"path" json:"path,omitempty"` } // UnmarshalYAML enables MountPoint to handle both a shorthand path and a structured object. diff --git a/toolkit/tools/imagecustomizerapi/os.go b/toolkit/tools/imagecustomizerapi/os.go index f79e05f880..ac68d0fa93 100644 --- a/toolkit/tools/imagecustomizerapi/os.go +++ b/toolkit/tools/imagecustomizerapi/os.go @@ -12,18 +12,19 @@ import ( // OS defines how each system present on the image is supposed to be configured. type OS struct { - Hostname string `yaml:"hostname"` - Packages Packages `yaml:"packages"` - SELinux SELinux `yaml:"selinux"` - KernelCommandLine KernelCommandLine `yaml:"kernelCommandLine"` - AdditionalFiles AdditionalFileList `yaml:"additionalFiles"` - AdditionalDirs DirConfigList `yaml:"additionalDirs"` - Users []User `yaml:"users"` - Services Services `yaml:"services"` - Modules ModuleList `yaml:"modules"` - Overlays *[]Overlay `yaml:"overlays"` - BootLoader BootLoader `yaml:"bootloader"` - Uki *Uki `yaml:"uki"` + Hostname string `yaml:"hostname" json:"hostname,omitempty"` + Packages Packages `yaml:"packages" json:"packages,omitempty"` + SELinux SELinux `yaml:"selinux" json:"selinux,omitempty"` + KernelCommandLine KernelCommandLine `yaml:"kernelCommandLine" json:"kernelCommandLine,omitempty"` + AdditionalFiles AdditionalFileList `yaml:"additionalFiles" json:"additionalFiles,omitempty"` + AdditionalDirs DirConfigList `yaml:"additionalDirs" json:"additionalDirs,omitempty"` + Users []User `yaml:"users" json:"users,omitempty"` + Services Services `yaml:"services" json:"services,omitempty"` + Modules ModuleList `yaml:"modules" json:"modules,omitempty"` + Overlays *[]Overlay `yaml:"overlays" json:"overlays,omitempty"` + BootLoader BootLoader `yaml:"bootloader" json:"bootloader,omitempty"` + Uki *Uki `yaml:"uki" json:"uki,omitempty"` + ImageHistory string `yaml:"imageHistory" json:"imageHistory,omitempty"` } func (s *OS) IsValid() error { @@ -39,6 +40,12 @@ func (s *OS) IsValid() error { } } + if s.ImageHistory != "" { + if s.ImageHistory != "none" { + return fmt.Errorf("invalid imageHistory (%s)", s.ImageHistory) + } + } + err = s.SELinux.IsValid() if err != nil { return fmt.Errorf("invalid selinux:\n%w", err) diff --git a/toolkit/tools/imagecustomizerapi/overlay.go b/toolkit/tools/imagecustomizerapi/overlay.go index 4fb27c8efe..dd6555ea77 100644 --- a/toolkit/tools/imagecustomizerapi/overlay.go +++ b/toolkit/tools/imagecustomizerapi/overlay.go @@ -10,13 +10,13 @@ import ( ) type Overlay struct { - LowerDirs []string `yaml:"lowerDirs"` - UpperDir string `yaml:"upperDir"` - WorkDir string `yaml:"workDir"` - MountPoint string `yaml:"mountPoint"` - IsInitrdOverlay bool `yaml:"isInitrdOverlay"` - MountDependencies []string `yaml:"mountDependencies"` - MountOptions string `yaml:"mountOptions"` + LowerDirs []string `yaml:"lowerDirs" json:"lowerDirs,omitempty"` + UpperDir string `yaml:"upperDir" json:"upperDir,omitempty"` + WorkDir string `yaml:"workDir" json:"workDir,omitempty"` + MountPoint string `yaml:"mountPoint" json:"mountPoint,omitempty"` + IsInitrdOverlay bool `yaml:"isInitrdOverlay" json:"isInitrdOverlay,omitempty"` + MountDependencies []string `yaml:"mountDependencies" json:"mountDependencies,omitempty"` + MountOptions string `yaml:"mountOptions" json:"mountOptions,omitempty"` } func (o *Overlay) IsValid() error { diff --git a/toolkit/tools/imagecustomizerapi/packagelist.go b/toolkit/tools/imagecustomizerapi/packagelist.go index 8c561a5e53..9aa1adbc69 100644 --- a/toolkit/tools/imagecustomizerapi/packagelist.go +++ b/toolkit/tools/imagecustomizerapi/packagelist.go @@ -4,7 +4,7 @@ package imagecustomizerapi type PackageList struct { - Packages []string `yaml:"packages"` + Packages []string `yaml:"packages" json:"packages,omitempty"` } func (s *PackageList) IsValid() error { diff --git a/toolkit/tools/imagecustomizerapi/packages.go b/toolkit/tools/imagecustomizerapi/packages.go index 9cb6ecbc9d..264565af1d 100644 --- a/toolkit/tools/imagecustomizerapi/packages.go +++ b/toolkit/tools/imagecustomizerapi/packages.go @@ -4,11 +4,11 @@ package imagecustomizerapi type Packages struct { - UpdateExistingPackages bool `yaml:"updateExistingPackages"` - InstallLists []string `yaml:"installLists"` - Install []string `yaml:"install"` - RemoveLists []string `yaml:"removeLists"` - Remove []string `yaml:"remove"` - UpdateLists []string `yaml:"updateLists"` - Update []string `yaml:"update"` + UpdateExistingPackages bool `yaml:"updateExistingPackages" json:"updateExistingPackages,omitempty"` + InstallLists []string `yaml:"installLists" json:"installLists,omitempty"` + Install []string `yaml:"install" json:"install,omitempty"` + RemoveLists []string `yaml:"removeLists" json:"removeLists,omitempty"` + Remove []string `yaml:"remove" json:"remove,omitempty"` + UpdateLists []string `yaml:"updateLists" json:"updateLists,omitempty"` + Update []string `yaml:"update" json:"update,omitempty"` } diff --git a/toolkit/tools/imagecustomizerapi/partition.go b/toolkit/tools/imagecustomizerapi/partition.go index 9a434b36f7..0be670c94d 100644 --- a/toolkit/tools/imagecustomizerapi/partition.go +++ b/toolkit/tools/imagecustomizerapi/partition.go @@ -10,18 +10,18 @@ import ( type Partition struct { // ID is used to correlate `Partition` objects with `FileSystem` objects. - Id string `yaml:"id"` + Id string `yaml:"id" json:"id,omitempty"` // Name is the label to assign to the partition. - Label string `yaml:"label"` + Label string `yaml:"label" json:"label,omitempty"` // Start is the offset where the partition begins (inclusive). // Note: When not provided, value is filled in by Disk.IsValid(). - Start *DiskSize `yaml:"start"` + Start *DiskSize `yaml:"start" json:"start,omitempty"` // End is the offset where the partition ends (exclusive). - End *DiskSize `yaml:"end"` + End *DiskSize `yaml:"end" json:"end,omitempty"` // Size is the size of the partition. - Size PartitionSize `yaml:"size"` + Size PartitionSize `yaml:"size" json:"size,omitempty"` // Type specifies the type of partition the partition is. - Type PartitionType `yaml:"type"` + Type PartitionType `yaml:"type" json:"type,omitempty"` } func (p *Partition) IsValid() error { diff --git a/toolkit/tools/imagecustomizerapi/password.go b/toolkit/tools/imagecustomizerapi/password.go index 4163622341..e86c736ef6 100644 --- a/toolkit/tools/imagecustomizerapi/password.go +++ b/toolkit/tools/imagecustomizerapi/password.go @@ -9,9 +9,9 @@ import ( type Password struct { // The way the password is provided. - Type PasswordType `yaml:"type"` + Type PasswordType `yaml:"type" json:"type,omitempty"` // The value of the password. - Value string `yaml:"value"` + Value string `yaml:"value" json:"value,omitempty"` } func (p *Password) IsValid() error { diff --git a/toolkit/tools/imagecustomizerapi/pxe.go b/toolkit/tools/imagecustomizerapi/pxe.go index 4df38c5f5f..98a55f8159 100644 --- a/toolkit/tools/imagecustomizerapi/pxe.go +++ b/toolkit/tools/imagecustomizerapi/pxe.go @@ -13,8 +13,8 @@ var PxeIsoDownloadProtocols = []string{"ftp://", "http://", "https://", "nfs://" // Iso defines how the generated iso media should be configured. type Pxe struct { - IsoImageBaseUrl string `yaml:"isoImageBaseUrl"` - IsoImageFileUrl string `yaml:"isoImageFileUrl"` + IsoImageBaseUrl string `yaml:"isoImageBaseUrl" json:"isoImageBaseUrl,omitempty"` + IsoImageFileUrl string `yaml:"isoImageFileUrl" json:"isoImageFileUrl,omitempty"` } func IsValidPxeUrl(urlString string) error { diff --git a/toolkit/tools/imagecustomizerapi/script.go b/toolkit/tools/imagecustomizerapi/script.go index a2de828de3..eafd959a79 100644 --- a/toolkit/tools/imagecustomizerapi/script.go +++ b/toolkit/tools/imagecustomizerapi/script.go @@ -10,20 +10,22 @@ import ( type Script struct { // Path is the path of the script file. // Mutually exclusive with 'Content'. - Path string `yaml:"path"` + Path string `yaml:"path" json:"path,omitempty"` // Content is the inline string content of the script to run. // Mutually exclusive with 'Path'. - Content string `yaml:"content"` + Content string `yaml:"content" json:"content,omitempty"` // Interpreter is the name or path of the process that will execute the script. // When 'Content' is specified, the default value is '/bin/sh'. // When 'Path' is specified and 'interpreter' is not specified, then the script file is executed directly. - Interpreter string `yaml:"interpreter"` + Interpreter string `yaml:"interpreter" json:"interpreter,omitempty"` // Arguments is a list of additional arguments to pass to the script. - Arguments []string `yaml:"arguments"` + Arguments []string `yaml:"arguments" json:"arguments,omitempty"` // EnvironmentVariables are a set of environment variables to set when executing the script. - EnvironmentVariables map[string]string `yaml:"environmentVariables"` + EnvironmentVariables map[string]string `yaml:"environmentVariables" json:"environmentVariables,omitempty"` // Name is an optional value used to reference the script in the logs. - Name string `yaml:"name"` + Name string `yaml:"name" json:"name,omitempty"` + + SHA256Hash string `yaml:"sha256hash" json:"sha256hash,omitempty"` } func (s *Script) IsValid() error { diff --git a/toolkit/tools/imagecustomizerapi/scripts.go b/toolkit/tools/imagecustomizerapi/scripts.go index a3cb07b146..5ecf729847 100644 --- a/toolkit/tools/imagecustomizerapi/scripts.go +++ b/toolkit/tools/imagecustomizerapi/scripts.go @@ -8,8 +8,8 @@ import ( ) type Scripts struct { - PostCustomization []Script `yaml:"postCustomization"` - FinalizeCustomization []Script `yaml:"finalizeCustomization"` + PostCustomization []Script `yaml:"postCustomization" json:"postCustomization,omitempty"` + FinalizeCustomization []Script `yaml:"finalizeCustomization" json:"finalizeCustomization,omitempty"` } func (s *Scripts) IsValid() error { diff --git a/toolkit/tools/imagecustomizerapi/selinux.go b/toolkit/tools/imagecustomizerapi/selinux.go index a838ca1ce3..aa2a27f1c5 100644 --- a/toolkit/tools/imagecustomizerapi/selinux.go +++ b/toolkit/tools/imagecustomizerapi/selinux.go @@ -9,7 +9,7 @@ import ( type SELinux struct { // SELinux specifies whether or not to enable SELinux on the image (and what mode SELinux should be in). - Mode SELinuxMode `yaml:"mode"` + Mode SELinuxMode `yaml:"mode" json:"mode,omitempty"` } func (s *SELinux) IsValid() error { diff --git a/toolkit/tools/imagecustomizerapi/service.go b/toolkit/tools/imagecustomizerapi/service.go index b3a7396c07..a008978788 100644 --- a/toolkit/tools/imagecustomizerapi/service.go +++ b/toolkit/tools/imagecustomizerapi/service.go @@ -16,8 +16,8 @@ func serviceNameIsValid(name string) error { } type Services struct { - Enable []string `yaml:"enable"` - Disable []string `yaml:"disable"` + Enable []string `yaml:"enable" json:"enable,omitempty"` + Disable []string `yaml:"disable" json:"disable,omitempty"` } func (s *Services) IsValid() error { diff --git a/toolkit/tools/imagecustomizerapi/storage.go b/toolkit/tools/imagecustomizerapi/storage.go index d131d8b00b..9ed352fd16 100644 --- a/toolkit/tools/imagecustomizerapi/storage.go +++ b/toolkit/tools/imagecustomizerapi/storage.go @@ -11,11 +11,11 @@ import ( ) type Storage struct { - ResetPartitionsUuidsType ResetPartitionsUuidsType `yaml:"resetPartitionsUuidsType"` - BootType BootType `yaml:"bootType"` - Disks []Disk `yaml:"disks"` - FileSystems []FileSystem `yaml:"filesystems"` - Verity []Verity `yaml:"verity"` + ResetPartitionsUuidsType ResetPartitionsUuidsType `yaml:"resetPartitionsUuidsType" json:"resetPartitionsUuidsType,omitempty"` + BootType BootType `yaml:"bootType" json:"bootType,omitempty"` + Disks []Disk `yaml:"disks" json:"disks,omitempty"` + FileSystems []FileSystem `yaml:"filesystems" json:"filesystems,omitempty"` + Verity []Verity `yaml:"verity" json:"verity,omitempty"` } func (s *Storage) IsValid() error { diff --git a/toolkit/tools/imagecustomizerapi/user.go b/toolkit/tools/imagecustomizerapi/user.go index 90a2ec92cc..e80b133993 100644 --- a/toolkit/tools/imagecustomizerapi/user.go +++ b/toolkit/tools/imagecustomizerapi/user.go @@ -10,16 +10,16 @@ import ( ) type User struct { - Name string `yaml:"name"` - UID *int `yaml:"uid"` - Password *Password `yaml:"password"` - PasswordExpiresDays *int64 `yaml:"passwordExpiresDays"` - SSHPublicKeyPaths []string `yaml:"sshPublicKeyPaths"` - SSHPublicKeys []string `yaml:"sshPublicKeys"` - PrimaryGroup string `yaml:"primaryGroup"` - SecondaryGroups []string `yaml:"secondaryGroups"` - StartupCommand string `yaml:"startupCommand"` - HomeDirectory string `yaml:"homeDirectory"` + Name string `yaml:"name" json:"name,omitempty"` + UID *int `yaml:"uid" json:"uid,omitempty"` + Password *Password `yaml:"password" json:"password,omitempty"` + PasswordExpiresDays *int64 `yaml:"passwordExpiresDays" json:"passwordExpiresDays,omitempty"` + SSHPublicKeyPaths []string `yaml:"sshPublicKeyPaths" json:"sshPublicKeyPaths,omitempty"` + SSHPublicKeys []string `yaml:"sshPublicKeys" json:"sshPublicKeys,omitempty"` + PrimaryGroup string `yaml:"primaryGroup" json:"primaryGroup,omitempty"` + SecondaryGroups []string `yaml:"secondaryGroups" json:"secondaryGroups,omitempty"` + StartupCommand string `yaml:"startupCommand" json:"startupCommand,omitempty"` + HomeDirectory string `yaml:"homeDirectory" json:"homeDirectory,omitempty"` } func (u *User) IsValid() error { diff --git a/toolkit/tools/imagecustomizerapi/verity.go b/toolkit/tools/imagecustomizerapi/verity.go index 338085247a..8aab0e41db 100644 --- a/toolkit/tools/imagecustomizerapi/verity.go +++ b/toolkit/tools/imagecustomizerapi/verity.go @@ -20,20 +20,20 @@ var ( type Verity struct { // ID is used to correlate `Verity` objects with `FileSystem` objects. - Id string `yaml:"id"` + Id string `yaml:"id" json:"id,omitempty"` // The name of the mapper block device. // Must be 'root' for the rootfs (/) filesystem. - Name string `yaml:"name"` + Name string `yaml:"name" json:"name,omitempty"` // The ID of the 'Partition' to use as the data partition. - DataDeviceId string `yaml:"dataDeviceId"` + DataDeviceId string `yaml:"dataDeviceId" json:"dataDeviceId,omitempty"` // The device ID type used to reference the data partition. - DataDeviceMountIdType MountIdentifierType `yaml:"dataDeviceMountIdType"` + DataDeviceMountIdType MountIdentifierType `yaml:"dataDeviceMountIdType" json:"dataDeviceMountIdType,omitempty"` // The ID of the 'Partition' to use as the hash partition. - HashDeviceId string `yaml:"hashDeviceId"` + HashDeviceId string `yaml:"hashDeviceId" json:"hashDeviceId,omitempty"` // The device ID type used to reference the data partition. - HashDeviceMountIdType MountIdentifierType `yaml:"hashDeviceMountIdType"` + HashDeviceMountIdType MountIdentifierType `yaml:"hashDeviceMountIdType" json:"hashDeviceMountIdType,omitempty"` // How to handle corruption. - CorruptionOption CorruptionOption `yaml:"corruptionOption"` + CorruptionOption CorruptionOption `yaml:"corruptionOption" json:"corruptionOption,omitempty"` // The filesystem config that points to this verity device. // Value is filled in by Storage.IsValid(). diff --git a/toolkit/tools/pkg/imagecustomizerlib/customizeos.go b/toolkit/tools/pkg/imagecustomizerlib/customizeos.go index bdf844dba6..b03ce357d2 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/customizeos.go +++ b/toolkit/tools/pkg/imagecustomizerlib/customizeos.go @@ -64,6 +64,13 @@ func doOsCustomizations(buildDir string, baseConfigPath string, config *imagecus return err } + if config.OS.ImageHistory != "none" { + err = addImageHistory(imageChroot, imageUuid, baseConfigPath, ToolVersion, buildTime, config) + if err != nil { + return err + } + } + err = handleBootLoader(baseConfigPath, config, imageConnection) if err != nil { return err diff --git a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go new file mode 100644 index 0000000000..ed844ab87f --- /dev/null +++ b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go @@ -0,0 +1,248 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +package imagecustomizerlib + +import ( + "encoding/json" + "fmt" + "log" + "os" + "path/filepath" + + "github.com/microsoft/azurelinux/toolkit/tools/imagecustomizerapi" + "github.com/microsoft/azurelinux/toolkit/tools/internal/file" + "github.com/microsoft/azurelinux/toolkit/tools/internal/logger" + "github.com/microsoft/azurelinux/toolkit/tools/internal/safechroot" +) + +type ImageHistory struct { + BuildTime string `yaml:"timestamp" json:"timestamp"` + ToolVersion string `yaml:"toolVersion" json:"toolVersion"` + ImageUuid string `yaml:"imageUuid" json:"imageUuid"` + Config imagecustomizerapi.Config `yaml:"config" json:"config"` +} + +func addImageHistory(imageChroot *safechroot.Chroot, imageUuid string, baseConfigPath string, toolVersion string, buildTime string, config *imagecustomizerapi.Config) error { + var err error + configCopy, err := deepCopyConfig(config) + if err != nil { + return err + } + err = modifyConfig(configCopy, baseConfigPath) + if err != nil { + return err + } + + logger.Log.Infof("Creating image customizer history file") + var allImageHistory []ImageHistory + + fmt.Println(imageChroot.RootDir()) + customizerLoggingDirPath := filepath.Join(".") + // customizerLoggingDirPath := filepath.Join(imageChroot.RootDir(), "/usr/share/image-customizer") + os.MkdirAll(customizerLoggingDirPath, 0755) + + imageHistoryFilePath := filepath.Join(customizerLoggingDirPath, "history.json") + + err = readImageHistory(imageHistoryFilePath, &allImageHistory) + if err != nil { + return err + } + + err = writeImageHistory(imageHistoryFilePath, allImageHistory, imageUuid, buildTime, toolVersion, configCopy) + if err != nil { + return err + } + + return nil +} + +func readImageHistory(imageHistoryFilePath string, allImageHistory *[]ImageHistory) error { + exists, err := file.PathExists(imageHistoryFilePath) + if err != nil { + return err + } + + if exists { + file, err := os.ReadFile(imageHistoryFilePath) + if err != nil { + log.Fatalf("Error reading file: %v", err) + } + + // Unmarshal the file content into the data slice + err = json.Unmarshal(file, &allImageHistory) + if err != nil { + log.Fatalf("Error unmarshalling JSON: %v", err) + } + } + return nil +} + +func writeImageHistory(imageHistoryFilePath string, allImageHistory []ImageHistory, imageUuid string, buildTime string, toolVersion string, configCopy *imagecustomizerapi.Config) error { + + // Add the current image history to the list + currentImageHistory := ImageHistory{ + BuildTime: buildTime, + ToolVersion: toolVersion, + ImageUuid: imageUuid, + Config: *configCopy, + } + allImageHistory = append(allImageHistory, currentImageHistory) + + jsonBytes, err := json.MarshalIndent(allImageHistory, "", " ") + if err != nil { + return err + } + file.Write(string(jsonBytes), imageHistoryFilePath) + return nil +} + +func deepCopyConfig(config *imagecustomizerapi.Config) (*imagecustomizerapi.Config, error) { + configCopy := &imagecustomizerapi.Config{} + data, err := json.Marshal(config) + if err != nil { + return nil, err + } + + err = json.Unmarshal(data, configCopy) + if err != nil { + return nil, err + } + + return configCopy, nil +} + +func modifyConfig(configCopy *imagecustomizerapi.Config, baseConfigPath string) error { + var err error + err = populateScriptsList(configCopy.Scripts, baseConfigPath) + if err != nil { + return err + } + + err = populateAdditionalFiles(configCopy.OS.AdditionalFiles, baseConfigPath) + if err != nil { + return err + } + + err = populateAdditionalDirs(configCopy.OS.AdditionalDirs, baseConfigPath) + if err != nil { + return err + } + + err = redactSshPublicKeys(configCopy.OS.Users) + if err != nil { + return err + } + return nil +} + +func populateAdditionalDirs(configAdditionalDirs imagecustomizerapi.DirConfigList, baseConfigPath string) error { + + for i := range configAdditionalDirs { + hashes := make(map[string]string) + sourcePath := configAdditionalDirs[i].Source + logger.Log.Infof("sourcePath: %s", sourcePath) + dirPath := file.GetAbsPathWithBase(baseConfigPath, sourcePath) + logger.Log.Infof("dirPath: %s", dirPath) + + destPath := configAdditionalDirs[i].Destination + logger.Log.Infof("destPath: %s", destPath) + // Walk the directory + err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + // Skip directories + if info.IsDir() { + return nil + } + + // Compute the relative path with respect to dirPath + relPath, err := filepath.Rel(dirPath, path) + if err != nil { + return fmt.Errorf("error computing relative path for %s: %w", path, err) + } + logger.Log.Infof("relPath: %s", relPath) + + // Normalize the relative path to ensure consistency + relPath = filepath.Clean(relPath) + logger.Log.Infof("relPath after clean: %s", relPath) + + hash, err := file.GenerateSHA256(path) + if err != nil { + return fmt.Errorf("failed to generate SHA256 for file %s: %w", path, err) + } + + hashes[relPath] = hash + return nil + }) + if err != nil { + return err + } + configAdditionalDirs[i].SHA256HashMap = hashes + } + return nil +} + +func populateAdditionalFiles(configAdditionalFiles imagecustomizerapi.AdditionalFileList, baseConfigPath string) error { + + for i := range configAdditionalFiles { + if configAdditionalFiles[i].Source == "" { + continue + } + absSourceFile := file.GetAbsPathWithBase(baseConfigPath, configAdditionalFiles[i].Source) + hash, err := file.GenerateSHA256(absSourceFile) + if err != nil { + return err + } + configAdditionalFiles[i].SHA256Hash = hash + } + return nil +} + +func redactSshPublicKeys(configUsers []imagecustomizerapi.User) error { + redactedString := "[redacted]" + for i := range configUsers { + user := configUsers[i] + for j := range user.SSHPublicKeys { + user.SSHPublicKeys[j] = redactedString + } + + } + return nil +} + +func populateScriptsList(scripts imagecustomizerapi.Scripts, baseConfigPath string) error { + + for i := range scripts.PostCustomization { + path := scripts.PostCustomization[i].Path + if path == "" { + // ignore entry if content is provided instead of path + continue + } + absSourceFile := file.GetAbsPathWithBase(baseConfigPath, path) + hash, err := file.GenerateSHA256(absSourceFile) + if err != nil { + return err + } + scripts.PostCustomization[i].SHA256Hash = hash + } + for i := range scripts.FinalizeCustomization { + path := scripts.FinalizeCustomization[i].Path + if path == "" { + // ignore entry if content is provided instead of path + continue + } + absSourceFile := file.GetAbsPathWithBase(baseConfigPath, path) + hash, err := file.GenerateSHA256(absSourceFile) + if err != nil { + return err + } + scripts.FinalizeCustomization[i].SHA256Hash = hash + + } + + return nil + +} From 75071420187855eb798476a8489d9e1bdf83dd3b Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Wed, 11 Dec 2024 18:11:30 +0000 Subject: [PATCH 02/23] add config docs --- docs/imagecustomizer/api/configuration.md | 29 ++++++++++--------- .../api/configuration/imagehistory.md | 10 +++++++ 2 files changed, 26 insertions(+), 13 deletions(-) create mode 100644 docs/imagecustomizer/api/configuration/imagehistory.md diff --git a/docs/imagecustomizer/api/configuration.md b/docs/imagecustomizer/api/configuration.md index cf12dcaf2d..1fbaa5a86e 100644 --- a/docs/imagecustomizer/api/configuration.md +++ b/docs/imagecustomizer/api/configuration.md @@ -43,7 +43,9 @@ The top level type for the YAML file is the [config](./configuration/config.md) 10. Write the `/etc/image-customizer-release` file. -11. If the bootloader [resetType](./configuration/bootloader.md#resettype-string) is set +11. Write the image history file. + +12. If the bootloader [resetType](./configuration/bootloader.md#resettype-string) is set to `hard-reset`, then reset the boot-loader. If the bootloader [resetType](./configuration/bootloader.md#resettype-string) is not @@ -51,34 +53,34 @@ The top level type for the YAML file is the [config](./configuration/config.md) [extraCommandLine](./configuration/kernelcommandline.md#extracommandline-string) value to the existing `grub.cfg` file. -12. Update the SELinux mode. [mode](./configuration/selinux.md#mode-string) +13. Update the SELinux mode. [mode](./configuration/selinux.md#mode-string) -13. If ([overlays](./configuration/os.md#overlays-overlay)) are specified, then add the +14. If ([overlays](./configuration/os.md#overlays-overlay)) are specified, then add the overlay driver and update the fstab file with the overlay mount information. -14. If a ([verity](./configuration/storage.md#verity-verity)) device is specified, then +15. If a ([verity](./configuration/storage.md#verity-verity)) device is specified, then add the dm-verity dracut driver and update the grub config. -15. Regenerate the initramfs file (if needed). +16. Regenerate the initramfs file (if needed). -16. Run ([postCustomization](./configuration/scripts.md#postcustomization-script)) scripts. +17. Run ([postCustomization](./configuration/scripts.md#postcustomization-script)) scripts. -17. Restore the `/etc/resolv.conf` file. +18. Restore the `/etc/resolv.conf` file. -18. If SELinux is enabled, call `setfiles`. +19. If SELinux is enabled, call `setfiles`. -19. Run finalize image scripts. ([finalizeCustomization](./configuration/scripts.md#finalizecustomization-script)) +20. Run finalize image scripts. ([finalizeCustomization](./configuration/scripts.md#finalizecustomization-script)) -20. If [--shrink-filesystems](./cli.md#shrink-filesystems) is specified, then shrink +21. If [--shrink-filesystems](./cli.md#shrink-filesystems) is specified, then shrink the file systems. -21. If a ([verity](./configuration/storage.md#verity-verity)) device is specified, then +22. If a ([verity](./configuration/storage.md#verity-verity)) device is specified, then create the hash tree and update the grub config. -22. If the output format is set to `iso`, copy additional iso media files. +23. If the output format is set to `iso`, copy additional iso media files. ([iso](./configuration/iso.md)) -23. If [--output-pxe-artifacts-dir](./cli.md#output-pxe-artifacts-dir) is specified, +24. If [--output-pxe-artifacts-dir](./cli.md#output-pxe-artifacts-dir) is specified, then export the ISO image contents to the specified folder. ## /etc/resolv.conf @@ -206,6 +208,7 @@ os: - [overlays](./configuration/os.md#overlays-overlay) ([overlay type](./configuration/overlay.md)) - [uki](./configuration/os.md#uki-uki) ([uki type](./configuration/uki.md)) - [kernels](./configuration/uki.md#kernels) + - [imageHistory](./configuration/imagehistory.md) - [scripts](./configuration/config.md#scripts-scripts) ([scripts type](./configuration/scripts.md)) - [postCustomization](./configuration/scripts.md#postcustomization-script) ([script type](./configuration/script.md)) - [path](./configuration/script.md#script-path) diff --git a/docs/imagecustomizer/api/configuration/imagehistory.md b/docs/imagecustomizer/api/configuration/imagehistory.md new file mode 100644 index 0000000000..c079ea76f8 --- /dev/null +++ b/docs/imagecustomizer/api/configuration/imagehistory.md @@ -0,0 +1,10 @@ +# imageHistory [string] + +Options for configuring image history. + +Set value to `none` to disable. + +```yaml +os: + imageHistory: none +``` \ No newline at end of file From be6317fb0c0393f7b7a6ca6d6c4d1efcf4118bdc Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Tue, 17 Dec 2024 21:51:58 +0000 Subject: [PATCH 03/23] partition size handling --- toolkit/tools/imagecustomizerapi/disksize.go | 17 +++++++ .../tools/imagecustomizerapi/partitionsize.go | 49 ++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/toolkit/tools/imagecustomizerapi/disksize.go b/toolkit/tools/imagecustomizerapi/disksize.go index 0f8d00e9ac..bbb68d9313 100644 --- a/toolkit/tools/imagecustomizerapi/disksize.go +++ b/toolkit/tools/imagecustomizerapi/disksize.go @@ -98,3 +98,20 @@ func parseDiskSize(diskSizeString string) (DiskSize, error) { return DiskSize(num), nil } + +// String returns the string representation of the DiskSize in the most appropriate unit +// such that it matches the input format. +func (s DiskSize) String() string { + switch { + case s%diskutils.TiB == 0: + return fmt.Sprintf("%dT", s/diskutils.TiB) + case s%diskutils.GiB == 0: + return fmt.Sprintf("%dG", s/diskutils.GiB) + case s%diskutils.MiB == 0: + return fmt.Sprintf("%dM", s/diskutils.MiB) + case s%diskutils.KiB == 0: + return fmt.Sprintf("%dK", s/diskutils.KiB) + default: + return fmt.Sprintf("%d", s) + } +} diff --git a/toolkit/tools/imagecustomizerapi/partitionsize.go b/toolkit/tools/imagecustomizerapi/partitionsize.go index 753560182c..a76a839aa7 100644 --- a/toolkit/tools/imagecustomizerapi/partitionsize.go +++ b/toolkit/tools/imagecustomizerapi/partitionsize.go @@ -4,6 +4,7 @@ package imagecustomizerapi import ( + "encoding/json" "fmt" "gopkg.in/yaml.v3" @@ -22,8 +23,8 @@ const ( ) type PartitionSize struct { - Type PartitionSizeType - Size DiskSize + Type PartitionSizeType `json:"type,omitempty"` + Size DiskSize `json:"size,omitempty"` } func (s *PartitionSize) IsValid() error { @@ -58,3 +59,47 @@ func (s *PartitionSize) UnmarshalYAML(value *yaml.Node) error { } return nil } + +func (s PartitionSize) MarshalJSON() ([]byte, error) { + switch s.Type { + case PartitionSizeTypeGrow: + return json.Marshal("grow") + case PartitionSizeTypeExplicit: + return json.Marshal(s.Size.String()) + default: + return json.Marshal(nil) + } +} + +func (s *PartitionSize) UnmarshalJSON(data []byte) error { + var err error + var stringValue string + err = json.Unmarshal(data, &stringValue) + if err != nil { + return fmt.Errorf("invalid partition size format: %w", err) + } + + switch stringValue { + case PartitionSizeGrow: + *s = PartitionSize{ + Type: PartitionSizeTypeGrow, + } + return nil + case "": + *s = PartitionSize{ + Type: PartitionSizeTypeUnset, + } + return nil + } + + diskSize, err := parseDiskSize(stringValue) + if err != nil { + return fmt.Errorf("%w:\nexpected format: grow | (K|M|G|T) (e.g. grow, 100M, 1G)", err) + } + + *s = PartitionSize{ + Type: PartitionSizeTypeExplicit, + Size: diskSize, + } + return nil +} From ab3ab6459693e7864519b04decfeb1ffa2eee212 Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Tue, 17 Dec 2024 22:09:21 +0000 Subject: [PATCH 04/23] disk size special handling --- toolkit/tools/imagecustomizerapi/disksize.go | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/toolkit/tools/imagecustomizerapi/disksize.go b/toolkit/tools/imagecustomizerapi/disksize.go index bbb68d9313..fb06da6b84 100644 --- a/toolkit/tools/imagecustomizerapi/disksize.go +++ b/toolkit/tools/imagecustomizerapi/disksize.go @@ -4,6 +4,7 @@ package imagecustomizerapi import ( + "encoding/json" "fmt" "regexp" "strconv" @@ -40,6 +41,28 @@ func (s *DiskSize) UnmarshalYAML(value *yaml.Node) error { return nil } +func (s DiskSize) MarshalJSON() ([]byte, error) { + return json.Marshal(s.String()) +} + +func (s *DiskSize) UnmarshalJSON(data []byte) error { + var err error + + var stringValue string + err = json.Unmarshal(data, &stringValue) + if err != nil { + return fmt.Errorf("failed to parse disk size:\n%w", err) + } + + diskSize, err := parseDiskSize(stringValue) + if err != nil { + return fmt.Errorf("%w:\nexpected format: (K|M|G|T) (e.g. 100M, 1G)", err) + } + + *s = diskSize + return nil +} + func (s DiskSize) HumanReadable() string { switch { case s%diskutils.TiB == 0: From b2b573b8121ebda98317ae1feeb690d982715198 Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Tue, 17 Dec 2024 22:27:22 +0000 Subject: [PATCH 05/23] dont marshal partition id --- toolkit/tools/imagecustomizerapi/filesystem.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/toolkit/tools/imagecustomizerapi/filesystem.go b/toolkit/tools/imagecustomizerapi/filesystem.go index 894ddd3599..1740dd8b5f 100644 --- a/toolkit/tools/imagecustomizerapi/filesystem.go +++ b/toolkit/tools/imagecustomizerapi/filesystem.go @@ -4,6 +4,7 @@ package imagecustomizerapi import ( + "encoding/json" "fmt" ) @@ -22,6 +23,23 @@ type FileSystem struct { PartitionId string } +// MarshalJSON without the PartitionId +func (f FileSystem) MarshalJSON() ([]byte, error) { + type FileSystemNoPartitionId struct { + DeviceId string `json:"deviceId,omitempty"` + Type FileSystemType `json:"type,omitempty"` + MountPoint *MountPoint `json:"mountPoint,omitempty"` + } + + fsNoPartition := FileSystemNoPartitionId{ + DeviceId: f.DeviceId, + Type: f.Type, + MountPoint: f.MountPoint, + } + + return json.Marshal(fsNoPartition) +} + // IsValid returns an error if the MountPoint is not valid func (f *FileSystem) IsValid() error { if f.DeviceId == "" { From aa6460fcd93a83cbfc5d430e9dc5d0e9003bbd6c Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Tue, 17 Dec 2024 23:26:30 +0000 Subject: [PATCH 06/23] meaningful error messages in imagehistory.go --- .../pkg/imagecustomizerlib/imagehistory.go | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go index ed844ab87f..13d0084b25 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go +++ b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go @@ -6,7 +6,6 @@ package imagecustomizerlib import ( "encoding/json" "fmt" - "log" "os" "path/filepath" @@ -27,11 +26,11 @@ func addImageHistory(imageChroot *safechroot.Chroot, imageUuid string, baseConfi var err error configCopy, err := deepCopyConfig(config) if err != nil { - return err + return fmt.Errorf("failed to deep copy config while writing image history: %w", err) } err = modifyConfig(configCopy, baseConfigPath) if err != nil { - return err + return fmt.Errorf("failed to modify config while writing image history: %w", err) } logger.Log.Infof("Creating image customizer history file") @@ -40,18 +39,21 @@ func addImageHistory(imageChroot *safechroot.Chroot, imageUuid string, baseConfi fmt.Println(imageChroot.RootDir()) customizerLoggingDirPath := filepath.Join(".") // customizerLoggingDirPath := filepath.Join(imageChroot.RootDir(), "/usr/share/image-customizer") - os.MkdirAll(customizerLoggingDirPath, 0755) + err = os.MkdirAll(customizerLoggingDirPath, 0755) + if err != nil { + return fmt.Errorf("failed to create customizer logging directory: %w", err) + } imageHistoryFilePath := filepath.Join(customizerLoggingDirPath, "history.json") err = readImageHistory(imageHistoryFilePath, &allImageHistory) if err != nil { - return err + return fmt.Errorf("failed to read image history: %w", err) } err = writeImageHistory(imageHistoryFilePath, allImageHistory, imageUuid, buildTime, toolVersion, configCopy) if err != nil { - return err + return fmt.Errorf("failed to write image history: %w", err) } return nil @@ -60,19 +62,18 @@ func addImageHistory(imageChroot *safechroot.Chroot, imageUuid string, baseConfi func readImageHistory(imageHistoryFilePath string, allImageHistory *[]ImageHistory) error { exists, err := file.PathExists(imageHistoryFilePath) if err != nil { - return err + return fmt.Errorf("failed to check if file exists: %w", err) } if exists { file, err := os.ReadFile(imageHistoryFilePath) if err != nil { - log.Fatalf("Error reading file: %v", err) + return fmt.Errorf("error reading image history file: %w", err) } - // Unmarshal the file content into the data slice err = json.Unmarshal(file, &allImageHistory) if err != nil { - log.Fatalf("Error unmarshalling JSON: %v", err) + return fmt.Errorf("error unmarshalling image history file: %w", err) } } return nil @@ -91,9 +92,14 @@ func writeImageHistory(imageHistoryFilePath string, allImageHistory []ImageHisto jsonBytes, err := json.MarshalIndent(allImageHistory, "", " ") if err != nil { - return err + return fmt.Errorf("failed to marshal image history: %w", err) + } + + err = file.Write(string(jsonBytes), imageHistoryFilePath) + if err != nil { + return fmt.Errorf("failed to write image history to file: %w", err) } - file.Write(string(jsonBytes), imageHistoryFilePath) + return nil } @@ -101,12 +107,12 @@ func deepCopyConfig(config *imagecustomizerapi.Config) (*imagecustomizerapi.Conf configCopy := &imagecustomizerapi.Config{} data, err := json.Marshal(config) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to marshal config: %w", err) } err = json.Unmarshal(data, configCopy) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to unmarshal config: %w", err) } return configCopy, nil @@ -114,24 +120,26 @@ func deepCopyConfig(config *imagecustomizerapi.Config) (*imagecustomizerapi.Conf func modifyConfig(configCopy *imagecustomizerapi.Config, baseConfigPath string) error { var err error + redactedString := "[redacted]" + err = populateScriptsList(configCopy.Scripts, baseConfigPath) if err != nil { - return err + return fmt.Errorf("failed to populate scripts list: %w", err) } err = populateAdditionalFiles(configCopy.OS.AdditionalFiles, baseConfigPath) if err != nil { - return err + return fmt.Errorf("failed to populate additional files: %w", err) } err = populateAdditionalDirs(configCopy.OS.AdditionalDirs, baseConfigPath) if err != nil { - return err + return fmt.Errorf("failed to populate additional dirs: %w", err) } - err = redactSshPublicKeys(configCopy.OS.Users) + err = redactSshPublicKeys(configCopy.OS.Users, redactedString) if err != nil { - return err + return fmt.Errorf("failed to redact ssh public keys: %w", err) } return nil } @@ -201,8 +209,7 @@ func populateAdditionalFiles(configAdditionalFiles imagecustomizerapi.Additional return nil } -func redactSshPublicKeys(configUsers []imagecustomizerapi.User) error { - redactedString := "[redacted]" +func redactSshPublicKeys(configUsers []imagecustomizerapi.User, redactedString string) error { for i := range configUsers { user := configUsers[i] for j := range user.SSHPublicKeys { @@ -218,7 +225,6 @@ func populateScriptsList(scripts imagecustomizerapi.Scripts, baseConfigPath stri for i := range scripts.PostCustomization { path := scripts.PostCustomization[i].Path if path == "" { - // ignore entry if content is provided instead of path continue } absSourceFile := file.GetAbsPathWithBase(baseConfigPath, path) @@ -228,10 +234,10 @@ func populateScriptsList(scripts imagecustomizerapi.Scripts, baseConfigPath stri } scripts.PostCustomization[i].SHA256Hash = hash } + for i := range scripts.FinalizeCustomization { path := scripts.FinalizeCustomization[i].Path if path == "" { - // ignore entry if content is provided instead of path continue } absSourceFile := file.GetAbsPathWithBase(baseConfigPath, path) @@ -244,5 +250,4 @@ func populateScriptsList(scripts imagecustomizerapi.Scripts, baseConfigPath stri } return nil - } From 22fa6810409cac3286d2525fbe00e59c7513feb5 Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Wed, 18 Dec 2024 00:20:54 +0000 Subject: [PATCH 07/23] improved additional dirs walking --- .../pkg/imagecustomizerlib/imagehistory.go | 48 ++++++++----------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go index 13d0084b25..2bb6a7fa87 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go +++ b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go @@ -24,6 +24,7 @@ type ImageHistory struct { func addImageHistory(imageChroot *safechroot.Chroot, imageUuid string, baseConfigPath string, toolVersion string, buildTime string, config *imagecustomizerapi.Config) error { var err error + logger.Log.Infof("Creating image customizer history file") configCopy, err := deepCopyConfig(config) if err != nil { return fmt.Errorf("failed to deep copy config while writing image history: %w", err) @@ -33,10 +34,8 @@ func addImageHistory(imageChroot *safechroot.Chroot, imageUuid string, baseConfi return fmt.Errorf("failed to modify config while writing image history: %w", err) } - logger.Log.Infof("Creating image customizer history file") var allImageHistory []ImageHistory - fmt.Println(imageChroot.RootDir()) customizerLoggingDirPath := filepath.Join(".") // customizerLoggingDirPath := filepath.Join(imageChroot.RootDir(), "/usr/share/image-customizer") err = os.MkdirAll(customizerLoggingDirPath, 0755) @@ -80,8 +79,6 @@ func readImageHistory(imageHistoryFilePath string, allImageHistory *[]ImageHisto } func writeImageHistory(imageHistoryFilePath string, allImageHistory []ImageHistory, imageUuid string, buildTime string, toolVersion string, configCopy *imagecustomizerapi.Config) error { - - // Add the current image history to the list currentImageHistory := ImageHistory{ BuildTime: buildTime, ToolVersion: toolVersion, @@ -145,48 +142,37 @@ func modifyConfig(configCopy *imagecustomizerapi.Config, baseConfigPath string) } func populateAdditionalDirs(configAdditionalDirs imagecustomizerapi.DirConfigList, baseConfigPath string) error { - for i := range configAdditionalDirs { hashes := make(map[string]string) sourcePath := configAdditionalDirs[i].Source - logger.Log.Infof("sourcePath: %s", sourcePath) dirPath := file.GetAbsPathWithBase(baseConfigPath, sourcePath) - logger.Log.Infof("dirPath: %s", dirPath) - destPath := configAdditionalDirs[i].Destination - logger.Log.Infof("destPath: %s", destPath) - // Walk the directory - err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { + addFileHashToMap := func(path string, d os.DirEntry, err error) error { if err != nil { return err } - // Skip directories - if info.IsDir() { + if d.IsDir() { return nil } - // Compute the relative path with respect to dirPath relPath, err := filepath.Rel(dirPath, path) if err != nil { return fmt.Errorf("error computing relative path for %s: %w", path, err) } - logger.Log.Infof("relPath: %s", relPath) - // Normalize the relative path to ensure consistency - relPath = filepath.Clean(relPath) - logger.Log.Infof("relPath after clean: %s", relPath) - - hash, err := file.GenerateSHA256(path) + hash, err := generateSHA256(path) if err != nil { - return fmt.Errorf("failed to generate SHA256 for file %s: %w", path, err) + return err } hashes[relPath] = hash return nil - }) + } + + err := filepath.WalkDir(dirPath, addFileHashToMap) if err != nil { - return err + return fmt.Errorf("error walking directory %s: %w", dirPath, err) } configAdditionalDirs[i].SHA256HashMap = hashes } @@ -194,13 +180,12 @@ func populateAdditionalDirs(configAdditionalDirs imagecustomizerapi.DirConfigLis } func populateAdditionalFiles(configAdditionalFiles imagecustomizerapi.AdditionalFileList, baseConfigPath string) error { - for i := range configAdditionalFiles { if configAdditionalFiles[i].Source == "" { continue } absSourceFile := file.GetAbsPathWithBase(baseConfigPath, configAdditionalFiles[i].Source) - hash, err := file.GenerateSHA256(absSourceFile) + hash, err := generateSHA256(absSourceFile) if err != nil { return err } @@ -221,14 +206,13 @@ func redactSshPublicKeys(configUsers []imagecustomizerapi.User, redactedString s } func populateScriptsList(scripts imagecustomizerapi.Scripts, baseConfigPath string) error { - for i := range scripts.PostCustomization { path := scripts.PostCustomization[i].Path if path == "" { continue } absSourceFile := file.GetAbsPathWithBase(baseConfigPath, path) - hash, err := file.GenerateSHA256(absSourceFile) + hash, err := generateSHA256(absSourceFile) if err != nil { return err } @@ -241,7 +225,7 @@ func populateScriptsList(scripts imagecustomizerapi.Scripts, baseConfigPath stri continue } absSourceFile := file.GetAbsPathWithBase(baseConfigPath, path) - hash, err := file.GenerateSHA256(absSourceFile) + hash, err := generateSHA256(absSourceFile) if err != nil { return err } @@ -251,3 +235,11 @@ func populateScriptsList(scripts imagecustomizerapi.Scripts, baseConfigPath stri return nil } + +func generateSHA256(path string) (hash string, err error) { + hash, err = file.GenerateSHA256(path) + if err != nil { + return "", fmt.Errorf("error generating SHA256 for %s: %w", path, err) + } + return hash, nil +} From 53dbdc3159d600944004a190ab62402978451970 Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Wed, 18 Dec 2024 01:14:23 +0000 Subject: [PATCH 08/23] logging dir --- toolkit/tools/pkg/imagecustomizerlib/imagehistory.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go index 2bb6a7fa87..f8a3839a5e 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go +++ b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go @@ -36,8 +36,7 @@ func addImageHistory(imageChroot *safechroot.Chroot, imageUuid string, baseConfi var allImageHistory []ImageHistory - customizerLoggingDirPath := filepath.Join(".") - // customizerLoggingDirPath := filepath.Join(imageChroot.RootDir(), "/usr/share/image-customizer") + customizerLoggingDirPath := filepath.Join(imageChroot.RootDir(), "/usr/share/image-customizer") err = os.MkdirAll(customizerLoggingDirPath, 0755) if err != nil { return fmt.Errorf("failed to create customizer logging directory: %w", err) From c48999abfc5785ed0a603838ce633dd4119da051 Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Wed, 18 Dec 2024 18:54:28 +0000 Subject: [PATCH 09/23] minor --- toolkit/tools/imagecustomizerapi/disksize.go | 2 +- toolkit/tools/imagecustomizerapi/partitionsize.go | 1 + toolkit/tools/pkg/imagecustomizerlib/imagehistory.go | 7 ++++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/toolkit/tools/imagecustomizerapi/disksize.go b/toolkit/tools/imagecustomizerapi/disksize.go index fb06da6b84..145c2d589f 100644 --- a/toolkit/tools/imagecustomizerapi/disksize.go +++ b/toolkit/tools/imagecustomizerapi/disksize.go @@ -122,7 +122,7 @@ func parseDiskSize(diskSizeString string) (DiskSize, error) { return DiskSize(num), nil } -// String returns the string representation of the DiskSize in the most appropriate unit +// String returns the string representation of DiskSize in the most appropriate unit // such that it matches the input format. func (s DiskSize) String() string { switch { diff --git a/toolkit/tools/imagecustomizerapi/partitionsize.go b/toolkit/tools/imagecustomizerapi/partitionsize.go index a76a839aa7..3a977aba30 100644 --- a/toolkit/tools/imagecustomizerapi/partitionsize.go +++ b/toolkit/tools/imagecustomizerapi/partitionsize.go @@ -73,6 +73,7 @@ func (s PartitionSize) MarshalJSON() ([]byte, error) { func (s *PartitionSize) UnmarshalJSON(data []byte) error { var err error + var stringValue string err = json.Unmarshal(data, &stringValue) if err != nil { diff --git a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go index f8a3839a5e..e0b69d2b6b 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go +++ b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go @@ -25,25 +25,26 @@ type ImageHistory struct { func addImageHistory(imageChroot *safechroot.Chroot, imageUuid string, baseConfigPath string, toolVersion string, buildTime string, config *imagecustomizerapi.Config) error { var err error logger.Log.Infof("Creating image customizer history file") + + // Deep copy the config to avoid modifying the original config configCopy, err := deepCopyConfig(config) if err != nil { return fmt.Errorf("failed to deep copy config while writing image history: %w", err) } + err = modifyConfig(configCopy, baseConfigPath) if err != nil { return fmt.Errorf("failed to modify config while writing image history: %w", err) } - var allImageHistory []ImageHistory - customizerLoggingDirPath := filepath.Join(imageChroot.RootDir(), "/usr/share/image-customizer") err = os.MkdirAll(customizerLoggingDirPath, 0755) if err != nil { return fmt.Errorf("failed to create customizer logging directory: %w", err) } - imageHistoryFilePath := filepath.Join(customizerLoggingDirPath, "history.json") + var allImageHistory []ImageHistory err = readImageHistory(imageHistoryFilePath, &allImageHistory) if err != nil { return fmt.Errorf("failed to read image history: %w", err) From 0d77ac52f8f6898504392cf1811c18eb76ab4e8e Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Thu, 19 Dec 2024 00:19:05 +0000 Subject: [PATCH 10/23] fix --- toolkit/tools/imagecustomizerapi/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolkit/tools/imagecustomizerapi/config.go b/toolkit/tools/imagecustomizerapi/config.go index 4f95ca7eb2..b186b6a618 100644 --- a/toolkit/tools/imagecustomizerapi/config.go +++ b/toolkit/tools/imagecustomizerapi/config.go @@ -15,7 +15,7 @@ type Config struct { Pxe *Pxe `yaml:"pxe" json:"pxe,omitempty"` OS *OS `yaml:"os" json:"os,omitempty"` Scripts Scripts `yaml:"scripts" json:"scripts,omitempty"` - PreviewFeatures []string `yaml:"previewFeatures json:"previewFeatures,omitempty"` + PreviewFeatures []string `yaml:"previewFeatures" json:"previewFeatures,omitempty"` } func (c *Config) IsValid() (err error) { From 66b5efa6c44e08a3d4b97b523ed1a6c44d44b26b Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Thu, 19 Dec 2024 00:35:29 +0000 Subject: [PATCH 11/23] omit --- .../tools/imagecustomizerapi/bootloader.go | 2 +- .../tools/imagecustomizerapi/filesystem.go | 20 +------------------ 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/toolkit/tools/imagecustomizerapi/bootloader.go b/toolkit/tools/imagecustomizerapi/bootloader.go index 32993400cc..eb2f217dff 100644 --- a/toolkit/tools/imagecustomizerapi/bootloader.go +++ b/toolkit/tools/imagecustomizerapi/bootloader.go @@ -8,7 +8,7 @@ import ( ) type BootLoader struct { - ResetType ResetBootLoaderType `yaml:"resetType"` + ResetType ResetBootLoaderType `yaml:"resetType" json:"resetType,omitempty"` } func (b *BootLoader) IsValid() error { diff --git a/toolkit/tools/imagecustomizerapi/filesystem.go b/toolkit/tools/imagecustomizerapi/filesystem.go index 1740dd8b5f..883e4d777d 100644 --- a/toolkit/tools/imagecustomizerapi/filesystem.go +++ b/toolkit/tools/imagecustomizerapi/filesystem.go @@ -4,7 +4,6 @@ package imagecustomizerapi import ( - "encoding/json" "fmt" ) @@ -20,24 +19,7 @@ type FileSystem struct { // If 'DeviceId' points at a verity device, this value is the 'Id' of the data partition. // Otherwise, it is the same as 'DeviceId'. // Value is filled in by Storage.IsValid(). - PartitionId string -} - -// MarshalJSON without the PartitionId -func (f FileSystem) MarshalJSON() ([]byte, error) { - type FileSystemNoPartitionId struct { - DeviceId string `json:"deviceId,omitempty"` - Type FileSystemType `json:"type,omitempty"` - MountPoint *MountPoint `json:"mountPoint,omitempty"` - } - - fsNoPartition := FileSystemNoPartitionId{ - DeviceId: f.DeviceId, - Type: f.Type, - MountPoint: f.MountPoint, - } - - return json.Marshal(fsNoPartition) + PartitionId string `json:"-"` } // IsValid returns an error if the MountPoint is not valid From 1ec98ba9f60887b6a52ddb86b0a84160e2ae3b34 Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Thu, 19 Dec 2024 00:38:46 +0000 Subject: [PATCH 12/23] remove yaml tags --- toolkit/tools/imagecustomizerapi/additionalfile.go | 2 +- toolkit/tools/imagecustomizerapi/dirconfig.go | 2 +- toolkit/tools/imagecustomizerapi/script.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/toolkit/tools/imagecustomizerapi/additionalfile.go b/toolkit/tools/imagecustomizerapi/additionalfile.go index bb0779ec5b..a8c12c96f7 100644 --- a/toolkit/tools/imagecustomizerapi/additionalfile.go +++ b/toolkit/tools/imagecustomizerapi/additionalfile.go @@ -24,7 +24,7 @@ type AdditionalFile struct { // The file permissions to set on the file. Permissions *FilePermissions `yaml:"permissions" json:"permissions,omitempty"` - SHA256Hash string `yaml:"sha256hash" json:"sha256hash,omitempty"` + SHA256Hash string `json:"sha256hash,omitempty"` } func (l AdditionalFileList) IsValid() (err error) { diff --git a/toolkit/tools/imagecustomizerapi/dirconfig.go b/toolkit/tools/imagecustomizerapi/dirconfig.go index ac76f8110a..6a55599ff3 100644 --- a/toolkit/tools/imagecustomizerapi/dirconfig.go +++ b/toolkit/tools/imagecustomizerapi/dirconfig.go @@ -30,7 +30,7 @@ type DirConfig struct { // Note: If this value is not specified in the config, the permissions for these directories will be set to 0755. ChildFilePermissions *FilePermissions `yaml:"childFilePermissions" json:"childFilePermissions,omitempty"` - SHA256HashMap map[string]string `yaml:"sha256hashmap" json:"sha256hashmap,omitempty"` + SHA256HashMap map[string]string `json:"sha256hashmap,omitempty"` } func (l *DirConfigList) IsValid() (err error) { diff --git a/toolkit/tools/imagecustomizerapi/script.go b/toolkit/tools/imagecustomizerapi/script.go index eafd959a79..8cd0099609 100644 --- a/toolkit/tools/imagecustomizerapi/script.go +++ b/toolkit/tools/imagecustomizerapi/script.go @@ -25,7 +25,7 @@ type Script struct { // Name is an optional value used to reference the script in the logs. Name string `yaml:"name" json:"name,omitempty"` - SHA256Hash string `yaml:"sha256hash" json:"sha256hash,omitempty"` + SHA256Hash string `json:"sha256hash,omitempty"` } func (s *Script) IsValid() error { From 834140d160828ecfbcb3a312545649e871d4bfc4 Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Thu, 19 Dec 2024 00:44:38 +0000 Subject: [PATCH 13/23] constants --- toolkit/tools/pkg/imagecustomizerlib/imagehistory.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go index e0b69d2b6b..86bc81afdf 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go +++ b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go @@ -22,6 +22,11 @@ type ImageHistory struct { Config imagecustomizerapi.Config `yaml:"config" json:"config"` } +const ( + customizerLoggingDir = "/usr/share/image-customizer" + historyFileName = "history.json" +) + func addImageHistory(imageChroot *safechroot.Chroot, imageUuid string, baseConfigPath string, toolVersion string, buildTime string, config *imagecustomizerapi.Config) error { var err error logger.Log.Infof("Creating image customizer history file") @@ -37,12 +42,12 @@ func addImageHistory(imageChroot *safechroot.Chroot, imageUuid string, baseConfi return fmt.Errorf("failed to modify config while writing image history: %w", err) } - customizerLoggingDirPath := filepath.Join(imageChroot.RootDir(), "/usr/share/image-customizer") + customizerLoggingDirPath := filepath.Join(imageChroot.RootDir(), customizerLoggingDir) err = os.MkdirAll(customizerLoggingDirPath, 0755) if err != nil { return fmt.Errorf("failed to create customizer logging directory: %w", err) } - imageHistoryFilePath := filepath.Join(customizerLoggingDirPath, "history.json") + imageHistoryFilePath := filepath.Join(customizerLoggingDirPath, historyFileName) var allImageHistory []ImageHistory err = readImageHistory(imageHistoryFilePath, &allImageHistory) From 2df524041bfb27ea250b850fbaa90710971d1ccd Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Thu, 19 Dec 2024 00:46:12 +0000 Subject: [PATCH 14/23] octal --- toolkit/tools/pkg/imagecustomizerlib/imagehistory.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go index 86bc81afdf..4a4c051dc6 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go +++ b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go @@ -43,7 +43,7 @@ func addImageHistory(imageChroot *safechroot.Chroot, imageUuid string, baseConfi } customizerLoggingDirPath := filepath.Join(imageChroot.RootDir(), customizerLoggingDir) - err = os.MkdirAll(customizerLoggingDirPath, 0755) + err = os.MkdirAll(customizerLoggingDirPath, 0o755) if err != nil { return fmt.Errorf("failed to create customizer logging directory: %w", err) } From 6e1794e29d5c34a21b63d9db09aa69b60f67cccc Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Thu, 19 Dec 2024 00:53:53 +0000 Subject: [PATCH 15/23] warning newline --- .../tools/imagecustomizerapi/partitionsize.go | 2 +- .../pkg/imagecustomizerlib/imagehistory.go | 38 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/toolkit/tools/imagecustomizerapi/partitionsize.go b/toolkit/tools/imagecustomizerapi/partitionsize.go index 3a977aba30..427332dca5 100644 --- a/toolkit/tools/imagecustomizerapi/partitionsize.go +++ b/toolkit/tools/imagecustomizerapi/partitionsize.go @@ -77,7 +77,7 @@ func (s *PartitionSize) UnmarshalJSON(data []byte) error { var stringValue string err = json.Unmarshal(data, &stringValue) if err != nil { - return fmt.Errorf("invalid partition size format: %w", err) + return fmt.Errorf("failed to parse partition size:\n%w", err) } switch stringValue { diff --git a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go index 4a4c051dc6..27cdf897ed 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go +++ b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go @@ -34,30 +34,30 @@ func addImageHistory(imageChroot *safechroot.Chroot, imageUuid string, baseConfi // Deep copy the config to avoid modifying the original config configCopy, err := deepCopyConfig(config) if err != nil { - return fmt.Errorf("failed to deep copy config while writing image history: %w", err) + return fmt.Errorf("failed to deep copy config while writing image history: \n%w", err) } err = modifyConfig(configCopy, baseConfigPath) if err != nil { - return fmt.Errorf("failed to modify config while writing image history: %w", err) + return fmt.Errorf("failed to modify config while writing image history: \n%w", err) } customizerLoggingDirPath := filepath.Join(imageChroot.RootDir(), customizerLoggingDir) err = os.MkdirAll(customizerLoggingDirPath, 0o755) if err != nil { - return fmt.Errorf("failed to create customizer logging directory: %w", err) + return fmt.Errorf("failed to create customizer logging directory: \n%w", err) } imageHistoryFilePath := filepath.Join(customizerLoggingDirPath, historyFileName) var allImageHistory []ImageHistory err = readImageHistory(imageHistoryFilePath, &allImageHistory) if err != nil { - return fmt.Errorf("failed to read image history: %w", err) + return fmt.Errorf("failed to read image history: \n%w", err) } err = writeImageHistory(imageHistoryFilePath, allImageHistory, imageUuid, buildTime, toolVersion, configCopy) if err != nil { - return fmt.Errorf("failed to write image history: %w", err) + return fmt.Errorf("failed to write image history: \n%w", err) } return nil @@ -66,18 +66,18 @@ func addImageHistory(imageChroot *safechroot.Chroot, imageUuid string, baseConfi func readImageHistory(imageHistoryFilePath string, allImageHistory *[]ImageHistory) error { exists, err := file.PathExists(imageHistoryFilePath) if err != nil { - return fmt.Errorf("failed to check if file exists: %w", err) + return fmt.Errorf("failed to check if file exists: \n%w", err) } if exists { file, err := os.ReadFile(imageHistoryFilePath) if err != nil { - return fmt.Errorf("error reading image history file: %w", err) + return fmt.Errorf("error reading image history file: \n%w", err) } err = json.Unmarshal(file, &allImageHistory) if err != nil { - return fmt.Errorf("error unmarshalling image history file: %w", err) + return fmt.Errorf("error unmarshalling image history file: \n%w", err) } } return nil @@ -94,12 +94,12 @@ func writeImageHistory(imageHistoryFilePath string, allImageHistory []ImageHisto jsonBytes, err := json.MarshalIndent(allImageHistory, "", " ") if err != nil { - return fmt.Errorf("failed to marshal image history: %w", err) + return fmt.Errorf("failed to marshal image history: \n%w", err) } err = file.Write(string(jsonBytes), imageHistoryFilePath) if err != nil { - return fmt.Errorf("failed to write image history to file: %w", err) + return fmt.Errorf("failed to write image history to file: \n%w", err) } return nil @@ -109,12 +109,12 @@ func deepCopyConfig(config *imagecustomizerapi.Config) (*imagecustomizerapi.Conf configCopy := &imagecustomizerapi.Config{} data, err := json.Marshal(config) if err != nil { - return nil, fmt.Errorf("failed to marshal config: %w", err) + return nil, fmt.Errorf("failed to marshal config: \n%w", err) } err = json.Unmarshal(data, configCopy) if err != nil { - return nil, fmt.Errorf("failed to unmarshal config: %w", err) + return nil, fmt.Errorf("failed to unmarshal config: \n%w", err) } return configCopy, nil @@ -126,22 +126,22 @@ func modifyConfig(configCopy *imagecustomizerapi.Config, baseConfigPath string) err = populateScriptsList(configCopy.Scripts, baseConfigPath) if err != nil { - return fmt.Errorf("failed to populate scripts list: %w", err) + return fmt.Errorf("failed to populate scripts list: \n%w", err) } err = populateAdditionalFiles(configCopy.OS.AdditionalFiles, baseConfigPath) if err != nil { - return fmt.Errorf("failed to populate additional files: %w", err) + return fmt.Errorf("failed to populate additional files: \n%w", err) } err = populateAdditionalDirs(configCopy.OS.AdditionalDirs, baseConfigPath) if err != nil { - return fmt.Errorf("failed to populate additional dirs: %w", err) + return fmt.Errorf("failed to populate additional dirs: \n%w", err) } err = redactSshPublicKeys(configCopy.OS.Users, redactedString) if err != nil { - return fmt.Errorf("failed to redact ssh public keys: %w", err) + return fmt.Errorf("failed to redact ssh public keys: \n%w", err) } return nil } @@ -163,7 +163,7 @@ func populateAdditionalDirs(configAdditionalDirs imagecustomizerapi.DirConfigLis relPath, err := filepath.Rel(dirPath, path) if err != nil { - return fmt.Errorf("error computing relative path for %s: %w", path, err) + return fmt.Errorf("error computing relative path for %s: \n%w", path, err) } hash, err := generateSHA256(path) @@ -177,7 +177,7 @@ func populateAdditionalDirs(configAdditionalDirs imagecustomizerapi.DirConfigLis err := filepath.WalkDir(dirPath, addFileHashToMap) if err != nil { - return fmt.Errorf("error walking directory %s: %w", dirPath, err) + return fmt.Errorf("error walking directory %s: \n%w", dirPath, err) } configAdditionalDirs[i].SHA256HashMap = hashes } @@ -244,7 +244,7 @@ func populateScriptsList(scripts imagecustomizerapi.Scripts, baseConfigPath stri func generateSHA256(path string) (hash string, err error) { hash, err = file.GenerateSHA256(path) if err != nil { - return "", fmt.Errorf("error generating SHA256 for %s: %w", path, err) + return "", fmt.Errorf("error generating SHA256 for %s: \n%w", path, err) } return hash, nil } From d3ddb54110275529d71a18e76f709d623788f941 Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Thu, 19 Dec 2024 01:09:02 +0000 Subject: [PATCH 16/23] remove continue --- .../pkg/imagecustomizerlib/imagehistory.go | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go index 27cdf897ed..9775ba2861 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go +++ b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go @@ -186,15 +186,14 @@ func populateAdditionalDirs(configAdditionalDirs imagecustomizerapi.DirConfigLis func populateAdditionalFiles(configAdditionalFiles imagecustomizerapi.AdditionalFileList, baseConfigPath string) error { for i := range configAdditionalFiles { - if configAdditionalFiles[i].Source == "" { - continue - } - absSourceFile := file.GetAbsPathWithBase(baseConfigPath, configAdditionalFiles[i].Source) - hash, err := generateSHA256(absSourceFile) - if err != nil { - return err + if configAdditionalFiles[i].Source != "" { + absSourceFile := file.GetAbsPathWithBase(baseConfigPath, configAdditionalFiles[i].Source) + hash, err := generateSHA256(absSourceFile) + if err != nil { + return err + } + configAdditionalFiles[i].SHA256Hash = hash } - configAdditionalFiles[i].SHA256Hash = hash } return nil } @@ -213,29 +212,26 @@ func redactSshPublicKeys(configUsers []imagecustomizerapi.User, redactedString s func populateScriptsList(scripts imagecustomizerapi.Scripts, baseConfigPath string) error { for i := range scripts.PostCustomization { path := scripts.PostCustomization[i].Path - if path == "" { - continue - } - absSourceFile := file.GetAbsPathWithBase(baseConfigPath, path) - hash, err := generateSHA256(absSourceFile) - if err != nil { - return err + if path != "" { + absSourceFile := file.GetAbsPathWithBase(baseConfigPath, path) + hash, err := generateSHA256(absSourceFile) + if err != nil { + return err + } + scripts.PostCustomization[i].SHA256Hash = hash } - scripts.PostCustomization[i].SHA256Hash = hash } for i := range scripts.FinalizeCustomization { path := scripts.FinalizeCustomization[i].Path - if path == "" { - continue - } - absSourceFile := file.GetAbsPathWithBase(baseConfigPath, path) - hash, err := generateSHA256(absSourceFile) - if err != nil { - return err + if path != "" { + absSourceFile := file.GetAbsPathWithBase(baseConfigPath, path) + hash, err := generateSHA256(absSourceFile) + if err != nil { + return err + } + scripts.FinalizeCustomization[i].SHA256Hash = hash } - scripts.FinalizeCustomization[i].SHA256Hash = hash - } return nil From 18dc1e82e5d39af825668437aa0c1800a02b089c Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Thu, 19 Dec 2024 01:20:35 +0000 Subject: [PATCH 17/23] image history enum --- .../tools/imagecustomizerapi/imagehistory.go | 26 +++++++++++++++++++ toolkit/tools/imagecustomizerapi/os.go | 9 +++---- .../pkg/imagecustomizerlib/customizeos.go | 2 +- 3 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 toolkit/tools/imagecustomizerapi/imagehistory.go diff --git a/toolkit/tools/imagecustomizerapi/imagehistory.go b/toolkit/tools/imagecustomizerapi/imagehistory.go new file mode 100644 index 0000000000..4e496d9bfe --- /dev/null +++ b/toolkit/tools/imagecustomizerapi/imagehistory.go @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +package imagecustomizerapi + +import ( + "fmt" +) + +type ImageHistory string + +const ( + ImageHistoryDefault ImageHistory = "" + ImageHistoryNone ImageHistory = "none" +) + +func (t ImageHistory) IsValid() error { + switch t { + case ImageHistoryDefault, ImageHistoryNone: + // All good. + return nil + + default: + return fmt.Errorf("invalid imageHistory value (%v)", t) + } +} diff --git a/toolkit/tools/imagecustomizerapi/os.go b/toolkit/tools/imagecustomizerapi/os.go index ac68d0fa93..b205efb23d 100644 --- a/toolkit/tools/imagecustomizerapi/os.go +++ b/toolkit/tools/imagecustomizerapi/os.go @@ -24,7 +24,7 @@ type OS struct { Overlays *[]Overlay `yaml:"overlays" json:"overlays,omitempty"` BootLoader BootLoader `yaml:"bootloader" json:"bootloader,omitempty"` Uki *Uki `yaml:"uki" json:"uki,omitempty"` - ImageHistory string `yaml:"imageHistory" json:"imageHistory,omitempty"` + ImageHistory ImageHistory `yaml:"imageHistory" json:"imageHistory,omitempty"` } func (s *OS) IsValid() error { @@ -40,10 +40,9 @@ func (s *OS) IsValid() error { } } - if s.ImageHistory != "" { - if s.ImageHistory != "none" { - return fmt.Errorf("invalid imageHistory (%s)", s.ImageHistory) - } + err = s.ImageHistory.IsValid() + if err != nil { + return fmt.Errorf("invalid imageHistory:\n%w", err) } err = s.SELinux.IsValid() diff --git a/toolkit/tools/pkg/imagecustomizerlib/customizeos.go b/toolkit/tools/pkg/imagecustomizerlib/customizeos.go index b03ce357d2..10e8895d03 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/customizeos.go +++ b/toolkit/tools/pkg/imagecustomizerlib/customizeos.go @@ -64,7 +64,7 @@ func doOsCustomizations(buildDir string, baseConfigPath string, config *imagecus return err } - if config.OS.ImageHistory != "none" { + if config.OS.ImageHistory != imagecustomizerapi.ImageHistoryNone { err = addImageHistory(imageChroot, imageUuid, baseConfigPath, ToolVersion, buildTime, config) if err != nil { return err From f596babd3601411d9885e42e8a33a6207227eb21 Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Thu, 19 Dec 2024 01:32:25 +0000 Subject: [PATCH 18/23] functions for common unmarshal --- toolkit/tools/imagecustomizerapi/disksize.go | 12 ++++------ .../tools/imagecustomizerapi/partitionsize.go | 23 ++++--------------- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/toolkit/tools/imagecustomizerapi/disksize.go b/toolkit/tools/imagecustomizerapi/disksize.go index 145c2d589f..a26e22f97b 100644 --- a/toolkit/tools/imagecustomizerapi/disksize.go +++ b/toolkit/tools/imagecustomizerapi/disksize.go @@ -32,13 +32,7 @@ func (s *DiskSize) UnmarshalYAML(value *yaml.Node) error { return fmt.Errorf("failed to parse disk size:\n%w", err) } - diskSize, err := parseDiskSize(stringValue) - if err != nil { - return fmt.Errorf("%w:\nexpected format: (K|M|G|T) (e.g. 100M, 1G)", err) - } - - *s = diskSize - return nil + return parseAndSetDiskSize(stringValue, s) } func (s DiskSize) MarshalJSON() ([]byte, error) { @@ -54,6 +48,10 @@ func (s *DiskSize) UnmarshalJSON(data []byte) error { return fmt.Errorf("failed to parse disk size:\n%w", err) } + return parseAndSetDiskSize(stringValue, s) +} + +func parseAndSetDiskSize(stringValue string, s *DiskSize) error { diskSize, err := parseDiskSize(stringValue) if err != nil { return fmt.Errorf("%w:\nexpected format: (K|M|G|T) (e.g. 100M, 1G)", err) diff --git a/toolkit/tools/imagecustomizerapi/partitionsize.go b/toolkit/tools/imagecustomizerapi/partitionsize.go index 427332dca5..09abbb0f26 100644 --- a/toolkit/tools/imagecustomizerapi/partitionsize.go +++ b/toolkit/tools/imagecustomizerapi/partitionsize.go @@ -40,24 +40,7 @@ func (s *PartitionSize) UnmarshalYAML(value *yaml.Node) error { return fmt.Errorf("failed to parse partition size:\n%w", err) } - switch stringValue { - case PartitionSizeGrow: - *s = PartitionSize{ - Type: PartitionSizeTypeGrow, - } - return nil - } - - diskSize, err := parseDiskSize(stringValue) - if err != nil { - return fmt.Errorf("%w:\nexpected format: grow | (K|M|G|T) (e.g. grow, 100M, 1G)", err) - } - - *s = PartitionSize{ - Type: PartitionSizeTypeExplicit, - Size: diskSize, - } - return nil + return parseAndSetPartitionSize(stringValue, s) } func (s PartitionSize) MarshalJSON() ([]byte, error) { @@ -80,6 +63,10 @@ func (s *PartitionSize) UnmarshalJSON(data []byte) error { return fmt.Errorf("failed to parse partition size:\n%w", err) } + return parseAndSetPartitionSize(stringValue, s) +} + +func parseAndSetPartitionSize(stringValue string, s *PartitionSize) error { switch stringValue { case PartitionSizeGrow: *s = PartitionSize{ From 995ba4d371790eda013738cb05b8c1b9cad90a20 Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Thu, 19 Dec 2024 01:50:47 +0000 Subject: [PATCH 19/23] omit package lists --- toolkit/tools/imagecustomizerapi/packages.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/toolkit/tools/imagecustomizerapi/packages.go b/toolkit/tools/imagecustomizerapi/packages.go index 264565af1d..23d50ed798 100644 --- a/toolkit/tools/imagecustomizerapi/packages.go +++ b/toolkit/tools/imagecustomizerapi/packages.go @@ -5,10 +5,10 @@ package imagecustomizerapi type Packages struct { UpdateExistingPackages bool `yaml:"updateExistingPackages" json:"updateExistingPackages,omitempty"` - InstallLists []string `yaml:"installLists" json:"installLists,omitempty"` + InstallLists []string `yaml:"installLists" json:"-"` Install []string `yaml:"install" json:"install,omitempty"` - RemoveLists []string `yaml:"removeLists" json:"removeLists,omitempty"` + RemoveLists []string `yaml:"removeLists" json:"-"` Remove []string `yaml:"remove" json:"remove,omitempty"` - UpdateLists []string `yaml:"updateLists" json:"updateLists,omitempty"` + UpdateLists []string `yaml:"updateLists" json:"-"` Update []string `yaml:"update" json:"update,omitempty"` } From 899bafbaeca0e440ad4a34de6afe311336881c68 Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Thu, 19 Dec 2024 01:53:57 +0000 Subject: [PATCH 20/23] rm space before newline --- .../pkg/imagecustomizerlib/imagehistory.go | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go index 9775ba2861..157810a97a 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go +++ b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go @@ -34,30 +34,30 @@ func addImageHistory(imageChroot *safechroot.Chroot, imageUuid string, baseConfi // Deep copy the config to avoid modifying the original config configCopy, err := deepCopyConfig(config) if err != nil { - return fmt.Errorf("failed to deep copy config while writing image history: \n%w", err) + return fmt.Errorf("failed to deep copy config while writing image history:\n%w", err) } err = modifyConfig(configCopy, baseConfigPath) if err != nil { - return fmt.Errorf("failed to modify config while writing image history: \n%w", err) + return fmt.Errorf("failed to modify config while writing image history:\n%w", err) } customizerLoggingDirPath := filepath.Join(imageChroot.RootDir(), customizerLoggingDir) err = os.MkdirAll(customizerLoggingDirPath, 0o755) if err != nil { - return fmt.Errorf("failed to create customizer logging directory: \n%w", err) + return fmt.Errorf("failed to create customizer logging directory:\n%w", err) } imageHistoryFilePath := filepath.Join(customizerLoggingDirPath, historyFileName) var allImageHistory []ImageHistory err = readImageHistory(imageHistoryFilePath, &allImageHistory) if err != nil { - return fmt.Errorf("failed to read image history: \n%w", err) + return fmt.Errorf("failed to read image history:\n%w", err) } err = writeImageHistory(imageHistoryFilePath, allImageHistory, imageUuid, buildTime, toolVersion, configCopy) if err != nil { - return fmt.Errorf("failed to write image history: \n%w", err) + return fmt.Errorf("failed to write image history:\n%w", err) } return nil @@ -66,18 +66,18 @@ func addImageHistory(imageChroot *safechroot.Chroot, imageUuid string, baseConfi func readImageHistory(imageHistoryFilePath string, allImageHistory *[]ImageHistory) error { exists, err := file.PathExists(imageHistoryFilePath) if err != nil { - return fmt.Errorf("failed to check if file exists: \n%w", err) + return fmt.Errorf("failed to check if file exists:\n%w", err) } if exists { file, err := os.ReadFile(imageHistoryFilePath) if err != nil { - return fmt.Errorf("error reading image history file: \n%w", err) + return fmt.Errorf("error reading image history file:\n%w", err) } err = json.Unmarshal(file, &allImageHistory) if err != nil { - return fmt.Errorf("error unmarshalling image history file: \n%w", err) + return fmt.Errorf("error unmarshalling image history file:\n%w", err) } } return nil @@ -94,12 +94,12 @@ func writeImageHistory(imageHistoryFilePath string, allImageHistory []ImageHisto jsonBytes, err := json.MarshalIndent(allImageHistory, "", " ") if err != nil { - return fmt.Errorf("failed to marshal image history: \n%w", err) + return fmt.Errorf("failed to marshal image history:\n%w", err) } err = file.Write(string(jsonBytes), imageHistoryFilePath) if err != nil { - return fmt.Errorf("failed to write image history to file: \n%w", err) + return fmt.Errorf("failed to write image history to file:\n%w", err) } return nil @@ -109,12 +109,12 @@ func deepCopyConfig(config *imagecustomizerapi.Config) (*imagecustomizerapi.Conf configCopy := &imagecustomizerapi.Config{} data, err := json.Marshal(config) if err != nil { - return nil, fmt.Errorf("failed to marshal config: \n%w", err) + return nil, fmt.Errorf("failed to marshal config:\n%w", err) } err = json.Unmarshal(data, configCopy) if err != nil { - return nil, fmt.Errorf("failed to unmarshal config: \n%w", err) + return nil, fmt.Errorf("failed to unmarshal config:\n%w", err) } return configCopy, nil @@ -126,22 +126,22 @@ func modifyConfig(configCopy *imagecustomizerapi.Config, baseConfigPath string) err = populateScriptsList(configCopy.Scripts, baseConfigPath) if err != nil { - return fmt.Errorf("failed to populate scripts list: \n%w", err) + return fmt.Errorf("failed to populate scripts list:\n%w", err) } err = populateAdditionalFiles(configCopy.OS.AdditionalFiles, baseConfigPath) if err != nil { - return fmt.Errorf("failed to populate additional files: \n%w", err) + return fmt.Errorf("failed to populate additional files:\n%w", err) } err = populateAdditionalDirs(configCopy.OS.AdditionalDirs, baseConfigPath) if err != nil { - return fmt.Errorf("failed to populate additional dirs: \n%w", err) + return fmt.Errorf("failed to populate additional dirs:\n%w", err) } err = redactSshPublicKeys(configCopy.OS.Users, redactedString) if err != nil { - return fmt.Errorf("failed to redact ssh public keys: \n%w", err) + return fmt.Errorf("failed to redact ssh public keys:\n%w", err) } return nil } @@ -163,7 +163,7 @@ func populateAdditionalDirs(configAdditionalDirs imagecustomizerapi.DirConfigLis relPath, err := filepath.Rel(dirPath, path) if err != nil { - return fmt.Errorf("error computing relative path for %s: \n%w", path, err) + return fmt.Errorf("error computing relative path for %s:\n%w", path, err) } hash, err := generateSHA256(path) @@ -177,7 +177,7 @@ func populateAdditionalDirs(configAdditionalDirs imagecustomizerapi.DirConfigLis err := filepath.WalkDir(dirPath, addFileHashToMap) if err != nil { - return fmt.Errorf("error walking directory %s: \n%w", dirPath, err) + return fmt.Errorf("error walking directory %s:\n%w", dirPath, err) } configAdditionalDirs[i].SHA256HashMap = hashes } @@ -240,7 +240,7 @@ func populateScriptsList(scripts imagecustomizerapi.Scripts, baseConfigPath stri func generateSHA256(path string) (hash string, err error) { hash, err = file.GenerateSHA256(path) if err != nil { - return "", fmt.Errorf("error generating SHA256 for %s: \n%w", path, err) + return "", fmt.Errorf("error generating SHA256 for %s:\n%w", path, err) } return hash, nil } From 10a4bb7825af74e8fb673580c8b3c1aec0cfb4f7 Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Thu, 19 Dec 2024 18:56:10 +0000 Subject: [PATCH 21/23] feedback --- .../tools/imagecustomizerapi/imagehistory.go | 2 +- .../pkg/imagecustomizerlib/imagehistory.go | 25 ++++++++----------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/toolkit/tools/imagecustomizerapi/imagehistory.go b/toolkit/tools/imagecustomizerapi/imagehistory.go index 4e496d9bfe..1fa1f67d6e 100644 --- a/toolkit/tools/imagecustomizerapi/imagehistory.go +++ b/toolkit/tools/imagecustomizerapi/imagehistory.go @@ -21,6 +21,6 @@ func (t ImageHistory) IsValid() error { return nil default: - return fmt.Errorf("invalid imageHistory value (%v)", t) + return fmt.Errorf("invalid imageHistory value (%s)", t) } } diff --git a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go index 157810a97a..e61c53c875 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go +++ b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go @@ -210,30 +210,27 @@ func redactSshPublicKeys(configUsers []imagecustomizerapi.User, redactedString s } func populateScriptsList(scripts imagecustomizerapi.Scripts, baseConfigPath string) error { - for i := range scripts.PostCustomization { - path := scripts.PostCustomization[i].Path - if path != "" { - absSourceFile := file.GetAbsPathWithBase(baseConfigPath, path) - hash, err := generateSHA256(absSourceFile) - if err != nil { - return err - } - scripts.PostCustomization[i].SHA256Hash = hash - } + if err := processScripts(scripts.PostCustomization, baseConfigPath); err != nil { + return fmt.Errorf("error processing PostCustomization scripts: %w", err) + } + if err := processScripts(scripts.FinalizeCustomization, baseConfigPath); err != nil { + return fmt.Errorf("error processing FinalizeCustomization scripts: %w", err) } + return nil +} - for i := range scripts.FinalizeCustomization { - path := scripts.FinalizeCustomization[i].Path +func processScripts(scripts []imagecustomizerapi.Script, baseConfigPath string) error { + for i := range scripts { + path := scripts[i].Path if path != "" { absSourceFile := file.GetAbsPathWithBase(baseConfigPath, path) hash, err := generateSHA256(absSourceFile) if err != nil { return err } - scripts.FinalizeCustomization[i].SHA256Hash = hash + scripts[i].SHA256Hash = hash } } - return nil } From ed84b68446369c5902281a1d53d1de0b1b921bef Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Thu, 19 Dec 2024 19:00:24 +0000 Subject: [PATCH 22/23] move docs --- .../imagecustomizer/api/configuration/imagehistory.md | 10 ---------- docs/imagecustomizer/api/configuration/os.md | 11 +++++++++++ 2 files changed, 11 insertions(+), 10 deletions(-) delete mode 100644 docs/imagecustomizer/api/configuration/imagehistory.md diff --git a/docs/imagecustomizer/api/configuration/imagehistory.md b/docs/imagecustomizer/api/configuration/imagehistory.md deleted file mode 100644 index c079ea76f8..0000000000 --- a/docs/imagecustomizer/api/configuration/imagehistory.md +++ /dev/null @@ -1,10 +0,0 @@ -# imageHistory [string] - -Options for configuring image history. - -Set value to `none` to disable. - -```yaml -os: - imageHistory: none -``` \ No newline at end of file diff --git a/docs/imagecustomizer/api/configuration/os.md b/docs/imagecustomizer/api/configuration/os.md index b74369ac79..8fa4b2e0c3 100644 --- a/docs/imagecustomizer/api/configuration/os.md +++ b/docs/imagecustomizer/api/configuration/os.md @@ -120,3 +120,14 @@ os: enable: - sshd ``` + +## imageHistory [string] + +Options for configuring image history. + +Set value to `none` to disable. + +```yaml +os: + imageHistory: none +``` From b231e75da4e1b4fcbe134dd561cd2bba99861aed Mon Sep 17 00:00:00 2001 From: Amrita Kohli Date: Thu, 19 Dec 2024 19:14:54 +0000 Subject: [PATCH 23/23] newline --- toolkit/tools/pkg/imagecustomizerlib/imagehistory.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go index e61c53c875..84dda92a2a 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go +++ b/toolkit/tools/pkg/imagecustomizerlib/imagehistory.go @@ -211,10 +211,10 @@ func redactSshPublicKeys(configUsers []imagecustomizerapi.User, redactedString s func populateScriptsList(scripts imagecustomizerapi.Scripts, baseConfigPath string) error { if err := processScripts(scripts.PostCustomization, baseConfigPath); err != nil { - return fmt.Errorf("error processing PostCustomization scripts: %w", err) + return fmt.Errorf("error processing PostCustomization scripts:\n%w", err) } if err := processScripts(scripts.FinalizeCustomization, baseConfigPath); err != nil { - return fmt.Errorf("error processing FinalizeCustomization scripts: %w", err) + return fmt.Errorf("error processing FinalizeCustomization scripts:\n%w", err) } return nil }