github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/cloudconfig/cloudinit/interface.go (about) 1 // Copyright 2011, 2013, 2015 Canonical Ltd. 2 // Copyright 2015 Cloudbase Solutions SRL 3 // Licensed under the AGPLv3, see LICENCE file for details. 4 5 // The cloudinit package implements a way of creating 6 // a cloud-init configuration file. 7 // See https://help.ubuntu.com/community/CloudInit. 8 package cloudinit 9 10 import ( 11 "github.com/juju/errors" 12 "github.com/juju/utils/os" 13 "github.com/juju/utils/packaging" 14 "github.com/juju/utils/packaging/commands" 15 "github.com/juju/utils/packaging/config" 16 "github.com/juju/utils/proxy" 17 "github.com/juju/utils/series" 18 "github.com/juju/utils/shell" 19 ) 20 21 // CloudConfig is the interface of all cloud-init cloudconfig options. 22 type CloudConfig interface { 23 // SetAttr sets an arbitrary attribute in the cloudinit config. 24 // The value will be marshalled according to the rules 25 // of the goyaml.Marshal. 26 SetAttr(string, interface{}) 27 28 // UnsetAttr unsets the attribute given from the cloudinit config. 29 // If the attribute has not been previously set, no error occurs. 30 UnsetAttr(string) 31 32 // GetSeries returns the series this CloudConfig was made for. 33 GetSeries() string 34 35 // CloudConfig also contains all the smaller interfaces for config 36 // management: 37 UserConfig 38 SystemUpdateConfig 39 SystemUpgradeConfig 40 PackageProxyConfig 41 PackageMirrorConfig 42 PackageSourcesConfig 43 PackagingConfig 44 RunCmdsConfig 45 BootCmdsConfig 46 EC2MetadataConfig 47 FinalMessageConfig 48 LocaleConfig 49 DeviceMountConfig 50 OutputConfig 51 SSHKeysConfig 52 RootUserConfig 53 WrittenFilesConfig 54 RenderConfig 55 AdvancedPackagingConfig 56 } 57 58 // UserConfig is the interface for managing all user-related settings. 59 type UserConfig interface { 60 // SetUser sets the username to be written in the config. 61 // NOTE: the user must exist beforehand, as no steps are taken to create it. 62 // NOTE: if not set, cloud-init defaults to using "ubuntu" 63 SetUser(string) 64 65 // UnsetUser unsets the "user" cloudinit config attribute set with SetUser. 66 // If the attribute has not been previously set, no error occurs. 67 UnsetUser() 68 69 // User returns the value set with SetUser or an empty string. 70 User() string 71 } 72 73 // SystemUpdateConfig is the interface for managing all system update options. 74 type SystemUpdateConfig interface { 75 // SetSystemUpdate sets whether the system should refresh the local package 76 // database on first boot. 77 // NOTE: This option is active in cloudinit by default and must be 78 // explicitly set to false if it is not desired. 79 SetSystemUpdate(bool) 80 81 // UnsetSystemUpdate unsets the package list updating option set by 82 // SetSystemUpdate, returning it to the cloudinit *default of true*. 83 // If the option has not previously been set, no error occurs. 84 UnsetSystemUpdate() 85 86 // SystemUpdate returns the value set with SetSystemUpdate or false 87 // NOTE: even though not set, the cloudinit-defined default is true. 88 SystemUpdate() bool 89 } 90 91 // SystemUpgradeConfig is the interface for managing all system upgrade settings. 92 type SystemUpgradeConfig interface { 93 // SetSystemUpgrade sets whether cloud-init should run the process of upgrading 94 // all the packages with available newer versions on the machine's *first* boot. 95 SetSystemUpgrade(bool) 96 97 // UnsetSystemUpgrade unsets the value set by SetSystemUpgrade. 98 // If the option has not previously been set, no error occurs. 99 UnsetSystemUpgrade() 100 101 // SystemUpgrade returns the value set by SetSystemUpgrade or 102 // false if no call to SetSystemUpgrade has been made. 103 SystemUpgrade() bool 104 } 105 106 // PackageProxyConfig is the interface for packaging proxy settings on a cloudconfig 107 type PackageProxyConfig interface { 108 // SetPackageProxy sets the URL to be used as a proxy by the 109 // specific package manager 110 SetPackageProxy(string) 111 112 // UnsetPackageProxy unsets the option set by SetPackageProxy 113 // If it has not been previously set, no error occurs 114 UnsetPackageProxy() 115 116 // PackageProxy returns the URL of the proxy server set using 117 // SetPackageProxy or an empty string if it has not been set 118 PackageProxy() string 119 } 120 121 // PackageMirrorConfig is the interface for package mirror settings on a cloudconfig. 122 type PackageMirrorConfig interface { 123 // SetPackageMirror sets the URL to be used as the mirror for 124 // pulling packages by the system's specific package manager. 125 SetPackageMirror(string) 126 127 // UnsetPackageMirror unsets the value set by SetPackageMirror 128 // If it has not been previously set, no error occurs. 129 UnsetPackageMirror() 130 131 // PackageMirror returns the URL of the package mirror set by 132 // SetPackageMirror or an empty string if not previously set. 133 PackageMirror() string 134 } 135 136 // PackageSourceConfig is the interface for package source settings on a cloudconfig. 137 type PackageSourcesConfig interface { 138 // AddPackageSource adds a new repository and optional key to be 139 // used as a package source by the system's specific package manager. 140 AddPackageSource(packaging.PackageSource) 141 142 // PackageSources returns all sources set with AddPackageSource. 143 PackageSources() []packaging.PackageSource 144 145 // AddPackagePreferences adds the necessary options and/or bootcmds to 146 // enable the given packaging.PackagePreferences. 147 AddPackagePreferences(packaging.PackagePreferences) 148 149 // PackagePreferences returns the previously-added PackagePreferences. 150 PackagePreferences() []packaging.PackagePreferences 151 } 152 153 // PackagingConfig is the interface for all packaging-related operations. 154 type PackagingConfig interface { 155 // AddPackage adds a package to be installed on *first* boot. 156 AddPackage(string) 157 158 // RemovePackage removes a package from the list of to be installed packages 159 // If the package has not been previously installed, no error occurs. 160 RemovePackage(string) 161 162 // Packages returns a list of all packages that will be installed. 163 Packages() []string 164 } 165 166 // RunCmdsConfig is the interface for all operations on first-boot commands. 167 type RunCmdsConfig interface { 168 // AddRunCmd adds a command to be executed on *first* boot. 169 // It can recieve any number of string arguments, which will be joined into 170 // a single command and passed to cloudinit to be executed. 171 // NOTE: metacharacters will *not* be escaped! 172 AddRunCmd(...string) 173 174 // AddScripts simply calls AddRunCmd on every string passed to it. 175 // NOTE: this means that each given string must be a full command plus 176 // all of its arguments. 177 // NOTE: metacharacters will not be escaped. 178 AddScripts(...string) 179 180 // RemoveRunCmd removes the given command from the list of commands to be 181 // run on first boot. If it has not been previously added, no error occurs. 182 RemoveRunCmd(string) 183 184 // RunCmds returns all the commands added with AddRunCmd or AddScript. 185 RunCmds() []string 186 } 187 188 // BootCmdsConfig is the interface for all operations on early-boot commands. 189 type BootCmdsConfig interface { 190 // AddBootCmd adds a command to be executed on *every* boot. 191 // It can recieve any number of string arguments, which will be joined into 192 // a single command. 193 // NOTE: metacharecters will not be escaped. 194 AddBootCmd(...string) 195 196 // RemoveBootCmd removes the given command from the list of commands to be 197 // run every boot. If it has not been previously added, no error occurs. 198 RemoveBootCmd(string) 199 200 // BootCmds returns all the commands added with AddBootCmd. 201 BootCmds() []string 202 } 203 204 // EC2MetadataConfig is the interface for all EC2-metadata related settings. 205 type EC2MetadataConfig interface { 206 // SetDisableEC2Metadata sets whether access to the EC2 metadata service is 207 // disabled early in boot via a null route. The default value is false. 208 // (route del -host 169.254.169.254 reject). 209 SetDisableEC2Metadata(bool) 210 211 // UnsetDisableEC2Metadata unsets the value set by SetDisableEC2Metadata, 212 // returning it to the cloudinit-defined value of false. 213 // If the option has not been previously set, no error occurs. 214 UnsetDisableEC2Metadata() 215 216 // DisableEC2Metadata returns the value set by SetDisableEC2Metadata or 217 // false if it has not been previously set. 218 DisableEC2Metadata() bool 219 } 220 221 // FinalMessageConfig is the interface for all settings related to the 222 // cloudinit final message. 223 type FinalMessageConfig interface { 224 // SetFinalMessage sets to message that will be written when the system has 225 // finished booting for the first time. By default, the message is: 226 // "cloud-init boot finished at $TIMESTAMP. Up $UPTIME seconds". 227 SetFinalMessage(string) 228 229 // UnsetFinalMessage unsets the value set by SetFinalMessage. 230 // If it has not been previously set, no error occurs. 231 UnsetFinalMessage() 232 233 // FinalMessage returns the value set using SetFinalMessage or an empty 234 // string if it has not previously been set. 235 FinalMessage() string 236 } 237 238 // LocaleConfig is the interface for all locale-related setting operations. 239 type LocaleConfig interface { 240 // SetLocale sets the locale; it defaults to en_US.UTF-8 241 SetLocale(string) 242 243 // UnsetLocale unsets the option set by SetLocale, returning it to the 244 // cloudinit-defined default of en_US.UTF-8 245 // If it has not been previously set, no error occurs 246 UnsetLocale() 247 248 // Locale returns the locale set with SetLocale 249 // If it has not been previously set, an empty string is returned 250 Locale() string 251 } 252 253 // DeviceMountConfig is the interface for all device mounting settings. 254 type DeviceMountConfig interface { 255 // AddMount adds takes arguments for installing a mount point in /etc/fstab 256 // The options are of the order and format specific to fstab entries: 257 // <device> <mountpoint> <filesystem> <options> <backup setting> <fsck priority> 258 AddMount(...string) 259 } 260 261 // OutputConfig is the interface for all stdout and stderr setting options. 262 type OutputConfig interface { 263 // SetOutput specifies the destinations of standard output and standard error of 264 // particular kinds of an output stream. 265 // Valid values include: 266 // - init: the output of cloudinit itself 267 // - config: cloud-config caused output 268 // - final: the final output of cloudinit (plus that set with SetFinalMessage) 269 // - all: all of the above 270 // Both stdout and stderr can take the following forms: 271 // - > file: write to given file. Will truncate of file exists 272 // - >>file: append to given file 273 // - | command: pipe output to given command 274 SetOutput(OutputKind, string, string) 275 276 // Output returns the destination set by SetOutput for the given OutputKind. 277 // If it has not been previously set, empty strings are returned. 278 Output(OutputKind) (string, string) 279 } 280 281 // SSHKeysConfig is the interface for all ssh key-related settings. 282 type SSHKeysConfig interface { 283 // AddSSHKey adds a pre-generated ssh key to the server keyring. 284 // Valid SSHKeyType options are: rsa_{public,private}, dsa_{public,private} 285 // Added keys will be written to /etc/ssh. 286 // As a result, new random keys are prevented from being generated. 287 AddSSHKey(SSHKeyType, string) 288 289 // AddSSHAuthorizedKeys adds a set of keys in ssh authorized_keys format 290 // that will be added to ~/.ssh/authorized_keys for the configured user (see SetUser). 291 AddSSHAuthorizedKeys(string) 292 } 293 294 // RootUserConfig is the interface for all root user-related settings. 295 type RootUserConfig interface { 296 // SetDisableRoot sets whether ssh login to the root account of the new server 297 // through the ssh authorized key provided with the config should be disabled. 298 // This option is set to true (ie. disabled) by default. 299 SetDisableRoot(bool) 300 301 // UnsetDisable unsets the value set with SetDisableRoot, returning it to the 302 // cloudinit-defined default of true. 303 UnsetDisableRoot() 304 305 // DisableRoot returns the value set by SetDisableRoot or false if the 306 // option had not been previously set. 307 DisableRoot() bool 308 } 309 310 // WrittenFilesConfig is the interface for all file writing operaions. 311 type WrittenFilesConfig interface { 312 // AddRunTextFile simply issues some AddRunCmd's to set the contents of a 313 // given file with the specified file permissions on *first* boot. 314 // NOTE: if the file already exists, it will be truncated. 315 AddRunTextFile(string, string, uint) 316 317 // AddBootTextFile simply issues some AddBootCmd's to set the contents of a 318 // given file with the specified file permissions on *every* boot. 319 // NOTE: if the file already exists, it will be truncated. 320 AddBootTextFile(string, string, uint) 321 322 // AddRunBinaryFile simply issues some AddRunCmd's to set the binary contents 323 // of a given file with the specified file permissions on *first* boot. 324 // NOTE: if the file already exists, it will be truncated. 325 AddRunBinaryFile(string, []byte, uint) 326 } 327 328 // RenderConfig provides various ways to render a CloudConfig. 329 type RenderConfig interface { 330 // Renders the current cloud config as valid YAML 331 RenderYAML() ([]byte, error) 332 333 // Renders a script that will execute the cloud config 334 // It is eiher used over ssh for bootstrapping and manual or locally by 335 // the local provider 336 RenderScript() (string, error) 337 338 // ShellRenderer renturns the shell renderer of this particular instance. 339 ShellRenderer() shell.Renderer 340 341 // getCommandsForAddingPackages is a helper function which returns all the 342 // necessary shell commands for adding all the configured package settings. 343 getCommandsForAddingPackages() ([]string, error) 344 } 345 346 // Makes two more advanced package commands available 347 type AdvancedPackagingConfig interface { 348 // Adds the necessary commands for installing the required packages for 349 // each OS is they are necessary. 350 AddPackageCommands( 351 aptProxySettings proxy.Settings, 352 aptMirror string, 353 addUpdateScripts bool, 354 addUpgradeScripts bool, 355 ) 356 357 // getPackageCommander returns the PackageCommander of the CloudConfig. 358 getPackageCommander() commands.PackageCommander 359 360 // getPackagingConfigurer returns the PackagingConfigurer of the CloudConfig. 361 getPackagingConfigurer() config.PackagingConfigurer 362 363 // addRequiredPackages is a helper to add packages that juju requires in 364 // order to operate. 365 addRequiredPackages() 366 367 //TODO(bogdanteleaga): this might be the same as the exported proxy setting up above, need 368 //to investigate how they're used 369 updateProxySettings(proxy.Settings) 370 371 // RequiresCloudArchiveCloudTools determines whether the cloudconfig 372 // requires the configuration of the cloud archive depending on its series. 373 RequiresCloudArchiveCloudTools() bool 374 375 // AddCloudArchiveCloudTools configures the cloudconfig to set up the cloud 376 // archive if it is required (eg: LTS'es). 377 AddCloudArchiveCloudTools() 378 } 379 380 // New returns a new Config with no options set. 381 func New(ser string) (CloudConfig, error) { 382 seriesos, err := series.GetOSFromSeries(ser) 383 if err != nil { 384 return nil, err 385 } 386 switch seriesos { 387 case os.Windows: 388 renderer, _ := shell.NewRenderer("powershell") 389 return &windowsCloudConfig{ 390 &cloudConfig{ 391 series: ser, 392 renderer: renderer, 393 attrs: make(map[string]interface{}), 394 }, 395 }, nil 396 case os.Ubuntu: 397 renderer, _ := shell.NewRenderer("bash") 398 return &ubuntuCloudConfig{ 399 &cloudConfig{ 400 series: ser, 401 paccmder: commands.NewAptPackageCommander(), 402 pacconfer: config.NewAptPackagingConfigurer(ser), 403 renderer: renderer, 404 attrs: make(map[string]interface{}), 405 }, 406 }, nil 407 case os.CentOS: 408 renderer, _ := shell.NewRenderer("bash") 409 return ¢OSCloudConfig{ 410 &cloudConfig{ 411 series: ser, 412 paccmder: commands.NewYumPackageCommander(), 413 pacconfer: config.NewYumPackagingConfigurer(ser), 414 renderer: renderer, 415 attrs: make(map[string]interface{}), 416 }, 417 }, nil 418 default: 419 return nil, errors.NotFoundf("cloudconfig for series %q", ser) 420 } 421 } 422 423 // SSHKeyType is the type of the four used key types passed to cloudinit 424 // through the cloudconfig 425 type SSHKeyType string 426 427 // The constant SSH key types sent to cloudinit through the cloudconfig 428 const ( 429 RSAPrivate SSHKeyType = "rsa_private" 430 RSAPublic SSHKeyType = "rsa_public" 431 DSAPrivate SSHKeyType = "dsa_private" 432 DSAPublic SSHKeyType = "dsa_public" 433 ) 434 435 // OutputKind represents the available destinations for command output as sent 436 // through the cloudnit cloudconfig 437 type OutputKind string 438 439 // The constant output redirection options available to be passed to cloudinit 440 const ( 441 // the output of cloudinit iself 442 OutInit OutputKind = "init" 443 // cloud-config caused output 444 OutConfig OutputKind = "config" 445 // the final output of cloudinit 446 OutFinal OutputKind = "final" 447 // all of the above 448 OutAll OutputKind = "all" 449 )