github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/cloudconfig/cloudinit/cloudinit_centos.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Copyright 2015 Cloudbase Solutions SRL 3 // Licensed under the AGPLv3, see LICENCE file for details. 4 5 package cloudinit 6 7 import ( 8 "fmt" 9 "strings" 10 11 "github.com/juju/packaging/v3" 12 "github.com/juju/packaging/v3/config" 13 "gopkg.in/yaml.v2" 14 15 corenetwork "github.com/juju/juju/core/network" 16 jujupackaging "github.com/juju/juju/packaging" 17 ) 18 19 // PackageHelper is the interface for configuring specific parameter of the package manager 20 type packageHelper interface { 21 // addPackageProxyCmd is a helper method which returns the corresponding runcmd 22 // to apply the package proxy settings. 23 addPackageProxyCmd(url string) string 24 25 //Returns the required packages, depending on the OS 26 getRequiredPackages() []string 27 } 28 29 // Implementation of PackageHelper for CentOS 30 type centOSHelper struct { 31 } 32 33 // Returns the list of required packages in CentOS 34 func (helper centOSHelper) getRequiredPackages() []string { 35 return []string{ 36 "curl", 37 "nmap-ncat", 38 "tmux", 39 "tar", 40 } 41 } 42 43 // addPackageProxyCmd is a helper method which returns the corresponding runcmd 44 // to apply the package proxy settings for CentOS 45 func (helper centOSHelper) addPackageProxyCmd(url string) string { 46 return fmt.Sprintf("/bin/echo 'proxy=%s' >> /etc/yum.conf", url) 47 } 48 49 // centOSCloudConfig is the cloudconfig type specific to CentOS machines. 50 // It simply contains a cloudConfig and adds the package management related 51 // methods for CentOS, which are mostly modeled as runcmds. 52 // It implements the cloudinit.Config interface. 53 type centOSCloudConfig struct { 54 *cloudConfig 55 helper packageHelper 56 } 57 58 // SetPackageProxy is defined on the PackageProxyConfig interface. 59 func (cfg *centOSCloudConfig) SetPackageProxy(url string) { 60 cfg.SetAttr("package_proxy", url) 61 } 62 63 // UnsetPackageProxy is defined on the PackageProxyConfig interface. 64 func (cfg *centOSCloudConfig) UnsetPackageProxy() { 65 cfg.UnsetAttr("package_proxy") 66 } 67 68 // PackageProxy is defined on the PackageProxyConfig interface. 69 func (cfg *centOSCloudConfig) PackageProxy() string { 70 proxy, _ := cfg.attrs["package_proxy"].(string) 71 return proxy 72 } 73 74 // SetPackageMirror is defined on the PackageMirrorConfig interface. 75 func (cfg *centOSCloudConfig) SetPackageMirror(url string) { 76 cfg.SetAttr("package_mirror", url) 77 } 78 79 // addPackageMirrorCmd is a helper function that returns the corresponding runcmds 80 // to apply the package mirror settings on a CentOS machine. 81 func addPackageMirrorCmd(cfg CloudConfig, url string) string { 82 return fmt.Sprintf(config.ReplaceCentOSMirror, url) 83 } 84 85 // UnsetPackageMirror is defined on the PackageMirrorConfig interface. 86 func (cfg *centOSCloudConfig) UnsetPackageMirror() { 87 cfg.UnsetAttr("package_mirror") 88 } 89 90 // PackageMirror is defined on the PackageMirrorConfig interface. 91 func (cfg *centOSCloudConfig) PackageMirror() string { 92 mirror, _ := cfg.attrs["package_mirror"].(string) 93 return mirror 94 } 95 96 // AddPackageSource is defined on the PackageSourcesConfig interface. 97 func (cfg *centOSCloudConfig) AddPackageSource(src packaging.PackageSource) { 98 cfg.attrs["package_sources"] = append(cfg.PackageSources(), src) 99 } 100 101 // PackageSources is defined on the PackageSourcesConfig interface. 102 func (cfg *centOSCloudConfig) PackageSources() []packaging.PackageSource { 103 sources, _ := cfg.attrs["package_sources"].([]packaging.PackageSource) 104 return sources 105 } 106 107 // AddPackagePreferences is defined on the PackageSourcesConfig interface. 108 func (cfg *centOSCloudConfig) AddPackagePreferences(prefs packaging.PackagePreferences) { 109 // TODO (aznashwan): research a way of using yum-priorities in the 110 // context of a single package and implement the appropriate runcmds. 111 } 112 113 // PackagePreferences is defined on the PackageSourcesConfig interface. 114 func (cfg *centOSCloudConfig) PackagePreferences() []packaging.PackagePreferences { 115 // TODO (aznashwan): add this when priorities in yum make sense. 116 return []packaging.PackagePreferences{} 117 } 118 119 // Render is defined on the the Renderer interface. 120 func (cfg *centOSCloudConfig) RenderYAML() ([]byte, error) { 121 // Save the fields that we will modify 122 var oldruncmds []string 123 oldruncmds = copyStringSlice(cfg.RunCmds()) 124 125 // check for package proxy setting and add commands: 126 var proxy string 127 if proxy = cfg.PackageProxy(); proxy != "" { 128 cfg.AddRunCmd(cfg.helper.addPackageProxyCmd(proxy)) 129 cfg.UnsetPackageProxy() 130 } 131 132 // check for package mirror settings and add commands: 133 var mirror string 134 if mirror = cfg.PackageMirror(); mirror != "" { 135 cfg.AddRunCmd(addPackageMirrorCmd(cfg, mirror)) 136 cfg.UnsetPackageMirror() 137 } 138 139 // add appropriate commands for package sources configuration: 140 srcs := cfg.PackageSources() 141 for _, src := range srcs { 142 cfg.AddScripts(addPackageSourceCmds(cfg, src)...) 143 } 144 cfg.UnsetAttr("package_sources") 145 146 data, err := yaml.Marshal(cfg.attrs) 147 if err != nil { 148 return nil, err 149 } 150 151 // Restore the modified fields 152 cfg.SetPackageProxy(proxy) 153 cfg.SetPackageMirror(mirror) 154 cfg.SetAttr("package_sources", srcs) 155 if oldruncmds != nil { 156 cfg.SetAttr("runcmd", oldruncmds) 157 } else { 158 cfg.UnsetAttr("runcmd") 159 } 160 161 return append([]byte("#cloud-config\n"), data...), nil 162 } 163 164 func (cfg *centOSCloudConfig) RenderScript() (string, error) { 165 return renderScriptCommon(cfg) 166 } 167 168 func (cfg *centOSCloudConfig) getCommandsForAddingPackages() ([]string, error) { 169 var cmds []string 170 171 if newMirror := cfg.PackageMirror(); newMirror != "" { 172 cmds = append(cmds, LogProgressCmd("Changing package mirror does not yet work on CentOS")) 173 // TODO(bogdanteleaga, aznashwan): This should work after a further PR 174 // where we add more mirrror options values to environs.Config 175 cmds = append(cmds, addPackageMirrorCmd(cfg, newMirror)) 176 } 177 178 pkgCmder := cfg.paccmder[jujupackaging.YumPackageManager] 179 for _, src := range cfg.PackageSources() { 180 // TODO(bogdanteleaga. aznashwan): Keys are usually offered by repositories, and you need to 181 // accept them. Check how this can be done non interactively. 182 cmds = append(cmds, LogProgressCmd("Adding yum repository: %s", src.URL)) 183 cmds = append(cmds, pkgCmder.AddRepositoryCmd(src.URL)) 184 } 185 186 // TODO(bogdanteleaga. aznashwan): Research what else needs to be done here 187 188 // Define the "package_get_loop" function 189 cmds = append(cmds, config.PackageManagerLoopFunction) 190 191 if cfg.SystemUpdate() { 192 cmds = append(cmds, LogProgressCmd("Running yum update")) 193 cmds = append(cmds, "package_manager_loop "+pkgCmder.UpdateCmd()) 194 } 195 if cfg.SystemUpgrade() { 196 cmds = append(cmds, LogProgressCmd("Running yum upgrade")) 197 cmds = append(cmds, "package_manager_loop "+pkgCmder.UpgradeCmd()) 198 } 199 200 pkgs := cfg.Packages() 201 if len(pkgs) > 0 { 202 cmds = append([]string{LogProgressCmd(fmt.Sprintf("Installing %s", strings.Join(pkgs, ", ")))}, cmds...) 203 } 204 for _, pkg := range pkgs { 205 cmds = append(cmds, "package_manager_loop "+pkgCmder.InstallCmd(pkg)) 206 } 207 return cmds, nil 208 } 209 210 // AddPackageCommands is defined on the AdvancedPackagingConfig interface. 211 func (cfg *centOSCloudConfig) AddPackageCommands( 212 proxyCfg PackageManagerProxyConfig, 213 addUpdateScripts bool, 214 addUpgradeScripts bool, 215 ) error { 216 return addPackageCommandsCommon( 217 cfg, 218 proxyCfg, 219 addUpdateScripts, 220 addUpgradeScripts, 221 ) 222 } 223 224 // addRequiredPackages is defined on the AdvancedPackagingConfig interface. 225 func (cfg *centOSCloudConfig) addRequiredPackages() { 226 packages := cfg.helper.getRequiredPackages() 227 for _, pack := range packages { 228 cfg.AddPackage(pack) 229 } 230 } 231 232 // TODO(bogdanteleaga, aznashwan): On ubuntu when we render the conf as yaml we 233 // have apt_proxy and when we render it as bash we use the equivalent of this. 234 // However on centOS even when rendering the YAML we use a helper function 235 // addPackageProxyCmds. Research if calling the same is fine. 236 func (cfg *centOSCloudConfig) updateProxySettings(PackageManagerProxyConfig) error { 237 return nil 238 } 239 240 // AddNetworkConfig is defined on the NetworkingConfig interface. 241 // TODO(wpk) This has to be implemented for CentOS on VSphere to work properly! 242 func (cfg *centOSCloudConfig) AddNetworkConfig(interfaces corenetwork.InterfaceInfos) error { 243 return nil 244 }