github.com/openshift/installer@v1.4.17/pkg/asset/agent/image/unconfigured_ignition.go (about) 1 package image 2 3 import ( 4 "context" 5 "os" 6 "path/filepath" 7 "strings" 8 9 igntypes "github.com/coreos/ignition/v2/config/v3_2/types" 10 "github.com/coreos/stream-metadata-go/arch" 11 "github.com/pkg/errors" 12 "github.com/sirupsen/logrus" 13 14 "github.com/openshift/installer/pkg/asset" 15 "github.com/openshift/installer/pkg/asset/agent/common" 16 "github.com/openshift/installer/pkg/asset/agent/manifests" 17 "github.com/openshift/installer/pkg/asset/agent/mirror" 18 "github.com/openshift/installer/pkg/asset/ignition" 19 "github.com/openshift/installer/pkg/asset/ignition/bootstrap" 20 "github.com/openshift/installer/pkg/types" 21 "github.com/openshift/installer/pkg/version" 22 ) 23 24 const ( 25 unconfiguredIgnitionFilename = "unconfigured-agent.ign" 26 ) 27 28 // GetConfigImageFiles returns the list of files or file paths to be included in the config-image. 29 func GetConfigImageFiles() []string { 30 return []string{ 31 "/etc/assisted/manifests/pull-secret.yaml", //nolint:gosec // not hardcoded credentials 32 "/etc/assisted/manifests/cluster-deployment.yaml", 33 "/etc/assisted/manifests/cluster-image-set.yaml", 34 "/etc/assisted/manifests/agent-cluster-install.yaml", 35 "/etc/assisted/manifests/infraenv.yaml", 36 "/etc/assisted/manifests", // optional nmstateconfig.yaml 37 "/etc/assisted/extra-manifests", // all files in directory 38 "/etc/assisted/hostconfig", // all files in directory 39 "/etc/assisted/hostnames", // all files in directory 40 "/etc/assisted/network", // all files in directory 41 "/etc/NetworkManager/conf.d/clientid.conf", 42 "/etc/issue", 43 "/etc/systemd/system.conf.d/10-default-env.conf", 44 "/root/.docker/config.json", 45 "/usr/local/share/start-cluster/start-cluster.env", 46 "/usr/local/share/assisted-service/assisted-service.env", 47 "/opt/agent/tls/kubeadmin-password.hash", //nolint:gosec // not hardcoded credentials 48 "/opt/agent/tls/admin-kubeconfig-signer.key", 49 "/opt/agent/tls/admin-kubeconfig-signer.crt", 50 "/opt/agent/tls/kube-apiserver-lb-signer.key", 51 "/opt/agent/tls/kube-apiserver-lb-signer.crt", 52 "/opt/agent/tls/kube-apiserver-localhost-signer.key", 53 "/opt/agent/tls/kube-apiserver-localhost-signer.crt", 54 "/opt/agent/tls/kube-apiserver-service-network-signer.key", 55 "/opt/agent/tls/kube-apiserver-service-network-signer.crt", 56 rendezvousHostEnvPath, // This file must be last in the list 57 } 58 } 59 60 // UnconfiguredIgnition is an asset that generates the agent installer unconfigured 61 // ignition file which excludes any cluster configuration. 62 type UnconfiguredIgnition struct { 63 Config *igntypes.Config 64 CPUArch string 65 File *asset.File 66 } 67 68 // Name returns the human-friendly name of the asset. 69 func (a *UnconfiguredIgnition) Name() string { 70 return "Agent Installer Unconfigured Ignition" 71 } 72 73 // Dependencies returns the assets on which the UnconfiguredIgnition asset depends. 74 func (a *UnconfiguredIgnition) Dependencies() []asset.Asset { 75 return []asset.Asset{ 76 &manifests.InfraEnv{}, 77 &manifests.AgentPullSecret{}, 78 &manifests.ClusterImageSet{}, 79 &manifests.NMStateConfig{}, 80 &mirror.RegistriesConf{}, 81 &mirror.CaBundle{}, 82 &common.InfraEnvID{}, 83 } 84 } 85 86 // Generate generates the agent installer unconfigured ignition. 87 func (a *UnconfiguredIgnition) Generate(_ context.Context, dependencies asset.Parents) error { 88 infraEnvAsset := &manifests.InfraEnv{} 89 infraEnvIDAsset := &common.InfraEnvID{} 90 clusterImageSetAsset := &manifests.ClusterImageSet{} 91 pullSecretAsset := &manifests.AgentPullSecret{} 92 nmStateConfigs := &manifests.NMStateConfig{} 93 dependencies.Get(infraEnvAsset, clusterImageSetAsset, pullSecretAsset, nmStateConfigs, infraEnvIDAsset) 94 95 infraEnv := infraEnvAsset.Config 96 clusterImageSet := clusterImageSetAsset.Config 97 98 config := igntypes.Config{ 99 Ignition: igntypes.Ignition{ 100 Version: igntypes.MaxVersion.String(), 101 }, 102 Passwd: igntypes.Passwd{ 103 Users: []igntypes.PasswdUser{ 104 { 105 Name: "core", 106 SSHAuthorizedKeys: []igntypes.SSHAuthorizedKey{ 107 igntypes.SSHAuthorizedKey(infraEnv.Spec.SSHAuthorizedKey), 108 }, 109 }, 110 }, 111 }, 112 } 113 114 // Default to x86_64 115 archName := arch.RpmArch(types.ArchitectureAMD64) 116 if infraEnv.Spec.CpuArchitecture != "" { 117 archName = infraEnv.Spec.CpuArchitecture 118 } 119 releaseImageList, err := releaseImageList(clusterImageSet.Spec.ReleaseImage, archName, []string{archName}) 120 if err != nil { 121 return err 122 } 123 124 registriesConfig := &mirror.RegistriesConf{} 125 registryCABundle := &mirror.CaBundle{} 126 dependencies.Get(registriesConfig, registryCABundle) 127 128 infraEnvID := infraEnvIDAsset.ID 129 logrus.Debug("Generated random infra-env id ", infraEnvID) 130 131 openshiftVersion, err := version.Version() 132 if err != nil { 133 return err 134 } 135 osImage, err := getOSImagesInfo(archName, openshiftVersion, DefaultCoreOSStreamGetter) 136 if err != nil { 137 return err 138 } 139 a.CPUArch = *osImage.CPUArchitecture 140 141 configImageFiles := strings.Join(GetConfigImageFiles(), ",") 142 143 agentTemplateData := &agentTemplateData{ 144 PullSecret: pullSecretAsset.GetPullSecretData(), 145 ReleaseImages: releaseImageList, 146 ReleaseImage: clusterImageSet.Spec.ReleaseImage, 147 ReleaseImageMirror: mirror.GetMirrorFromRelease(clusterImageSet.Spec.ReleaseImage, registriesConfig), 148 HaveMirrorConfig: len(registriesConfig.MirrorConfig) > 0, 149 PublicContainerRegistries: getPublicContainerRegistries(registriesConfig), 150 InfraEnvID: infraEnvID, 151 OSImage: osImage, 152 Proxy: infraEnv.Spec.Proxy, 153 ConfigImageFiles: configImageFiles, 154 } 155 156 err = bootstrap.AddStorageFiles(&config, "/", "agent/files", agentTemplateData) 157 if err != nil { 158 return err 159 } 160 161 err = addBootstrapScripts(&config, clusterImageSetAsset.Config.Spec.ReleaseImage) 162 if err != nil { 163 return err 164 } 165 166 enabledServices := getDefaultEnabledServices() 167 if len(nmStateConfigs.StaticNetworkConfig) > 0 { 168 err = addStaticNetworkConfig(&config, nmStateConfigs.StaticNetworkConfig) 169 if err != nil { 170 return err 171 } 172 173 enabledServices = append(enabledServices, "pre-network-manager-config.service") 174 } else { 175 // Include the script in case it is needed in config step 176 nmStateScriptFilePath := "/usr/local/bin/pre-network-manager-config.sh" 177 nmStateScript := ignition.FileFromBytes(nmStateScriptFilePath, "root", 0755, []byte(manifests.PreNetworkConfigScript)) 178 config.Storage.Files = append(config.Storage.Files, nmStateScript) 179 } 180 181 ztpManifestsToInclude := [...]asset.File{ 182 *infraEnvAsset.File, 183 *clusterImageSetAsset.File, 184 *pullSecretAsset.File, 185 } 186 187 for _, file := range ztpManifestsToInclude { 188 manifestFile := ignition.FileFromBytes(filepath.Join(manifestPath, filepath.Base(file.Filename)), 189 "root", 0600, file.Data) 190 config.Storage.Files = append(config.Storage.Files, manifestFile) 191 } 192 193 // the agent-check-config-image.service added only to the unconfigured ignition 194 enabledServices = append(enabledServices, "agent-check-config-image.service") 195 err = bootstrap.AddSystemdUnits(&config, "agent/systemd/units", agentTemplateData, enabledServices) 196 if err != nil { 197 return err 198 } 199 200 addMirrorData(&config, registriesConfig, registryCABundle) 201 202 a.Config = &config 203 204 if err := a.generateFile(unconfiguredIgnitionFilename); err != nil { 205 return err 206 } 207 208 return nil 209 } 210 211 // PersistToFile writes the unconfigured ignition in the assets folder. 212 func (a *UnconfiguredIgnition) PersistToFile(directory string) error { 213 if a.File == nil { 214 return errors.New("attempting to persist a UnconfiguredIgnition that has not been generated") 215 } 216 unconfiguredIgnFile := filepath.Join(directory, a.File.Filename) 217 218 err := os.WriteFile(unconfiguredIgnFile, a.File.Data, 0o644) //nolint:gosec // no sensitive info 219 if err != nil { 220 return err 221 } 222 223 logrus.Infof("Unconfigured-Ignition created in: %s", unconfiguredIgnFile) 224 225 return nil 226 } 227 228 func (a *UnconfiguredIgnition) generateFile(filename string) error { 229 data, err := ignition.Marshal(a.Config) 230 if err != nil { 231 return errors.Wrap(err, "failed to Marshal UnconfiguredIgnition config") 232 } 233 a.File = &asset.File{ 234 Filename: filename, 235 Data: data, 236 } 237 return nil 238 } 239 240 // Load returns the UnconfiguredIgnition from disk. 241 func (a *UnconfiguredIgnition) Load(f asset.FileFetcher) (bool, error) { 242 // The UnconfiguredIgnition will not be needed by another asset so load is noop. 243 // This is implemented because it is required by WritableAsset 244 return false, nil 245 } 246 247 // Files returns the files generated by the asset. 248 func (a *UnconfiguredIgnition) Files() []*asset.File { 249 // Return empty array because File will never be loaded. 250 return []*asset.File{} 251 }