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