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 &centOSCloudConfig{
   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  )