github.com/openshift/installer@v1.4.17/pkg/asset/agent/configimage/configiso.go (about) 1 package configimage 2 3 import ( 4 "context" 5 "os" 6 "path/filepath" 7 "strings" 8 9 "github.com/pkg/errors" 10 "github.com/sirupsen/logrus" 11 "github.com/vincent-petithory/dataurl" 12 13 "github.com/openshift/assisted-image-service/pkg/isoeditor" 14 "github.com/openshift/installer/pkg/asset" 15 "github.com/openshift/installer/pkg/asset/agent/image" 16 ) 17 18 const ( 19 configImageFilename = "agentconfig.noarch.iso" 20 configImageLabel = "agent_configimage" 21 configCpioArchive = "config.gz" 22 ) 23 24 // ConfigImage is an asset that generates a configuration ISO that can be used configure hosts. 25 type ConfigImage struct { 26 tmpPath string 27 } 28 29 var _ asset.WritableAsset = (*ConfigImage)(nil) 30 31 // Dependencies returns the assets on which the Config asset depends. 32 func (a *ConfigImage) Dependencies() []asset.Asset { 33 return []asset.Asset{ 34 &image.Ignition{}, 35 } 36 } 37 38 // Generate generates the configuration image file. 39 func (a *ConfigImage) Generate(_ context.Context, dependencies asset.Parents) error { 40 ignition := &image.Ignition{} 41 42 dependencies.Get(ignition) 43 44 ca := image.NewCpioArchive() 45 46 // Walk the list of ignition files. 47 // For the ones to be included in the configimage add to cpio archive 48 for _, file := range ignition.Config.Storage.Files { 49 filename := file.Node.Path 50 mode := *file.FileEmbedded1.Mode 51 if includeFileInImage(filename) { 52 logrus.Debugf("Including file %s", filename) 53 contents := "" 54 if file.FileEmbedded1.Contents.Source != nil { 55 output, err := dataurl.DecodeString(*file.FileEmbedded1.Contents.Source) 56 if err != nil { 57 return errors.Wrapf(err, "decode string failed for %s", filename) 58 } 59 contents = string(output.Data) 60 } 61 62 err := ca.StoreBytes(filename, []byte(contents), mode) 63 if err != nil { 64 return errors.Wrapf(err, "failure storing file %s in cpio", filename) 65 } 66 } 67 } 68 69 // Save the cpi archive to a temp file 70 tmpPath, err := os.MkdirTemp("", "agent") 71 if err != nil { 72 return err 73 } 74 a.tmpPath = tmpPath 75 76 output := filepath.Join(tmpPath, configCpioArchive) 77 78 err = ca.Save(output) 79 if err != nil { 80 return errors.Wrapf(err, "failure saving cpio file %s", configCpioArchive) 81 } 82 83 return nil 84 } 85 86 // PersistToFile writes the iso image in the assets folder. 87 func (a *ConfigImage) PersistToFile(directory string) error { 88 defer os.RemoveAll(a.tmpPath) 89 90 // If the tmpPath are not set then it means that either one of the Config 91 // dependencies or the asset itself failed for some reason 92 if a.tmpPath == "" { 93 return errors.New("cannot generate Config image due to configuration errors") 94 } 95 96 configImageFile := filepath.Join(directory, configImageFilename) 97 98 // Remove symlink if it exists 99 os.Remove(configImageFile) 100 101 err := isoeditor.Create(configImageFile, a.tmpPath, configImageLabel) 102 if err != nil { 103 return err 104 } 105 106 return nil 107 } 108 109 // Name returns the human-friendly name of the asset. 110 func (a *ConfigImage) Name() string { 111 return "Agent Config ISO" 112 } 113 114 // Load returns the ISO from disk. 115 func (a *ConfigImage) Load(f asset.FileFetcher) (bool, error) { 116 // The ISO will not be needed by another asset so load is noop. 117 // This is implemented because it is required by WritableAsset 118 return false, nil 119 } 120 121 // Files returns the files generated by the asset. 122 func (a *ConfigImage) Files() []*asset.File { 123 // Return empty array because File will never be loaded. 124 return []*asset.File{} 125 } 126 127 func includeFileInImage(f string) bool { 128 fileFilters := image.GetConfigImageFiles() 129 for _, filter := range fileFilters { 130 if strings.Contains(f, filter) { 131 return true 132 } 133 } 134 return false 135 }