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