launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/agent/format-1.12.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package agent
     5  
     6  import (
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"path"
    11  
    12  	"launchpad.net/goyaml"
    13  
    14  	"launchpad.net/juju-core/state"
    15  	"launchpad.net/juju-core/state/api"
    16  	"launchpad.net/juju-core/utils"
    17  )
    18  
    19  const format_1_12 = "format 1.12"
    20  
    21  // formatter_1_12 is the formatter for the 1.12 format.
    22  type formatter_1_12 struct {
    23  }
    24  
    25  // format_1_12Serialization holds information stored in the agent.conf file.
    26  type format_1_12Serialization struct {
    27  	// StateServerCert and StateServerKey hold the state server
    28  	// certificate and private key in PEM format.
    29  	StateServerCert []byte `yaml:",omitempty"`
    30  	StateServerKey  []byte `yaml:",omitempty"`
    31  
    32  	StatePort int `yaml:",omitempty"`
    33  	APIPort   int `yaml:",omitempty"`
    34  
    35  	// OldPassword specifies a password that should be
    36  	// used to connect to the state if StateInfo.Password
    37  	// is blank or invalid.
    38  	OldPassword string
    39  
    40  	// MachineNonce is set at provisioning/bootstrap time and used to
    41  	// ensure the agent is running on the correct instance.
    42  	MachineNonce string
    43  
    44  	// StateInfo specifies how the agent should connect to the
    45  	// state.  The password may be empty if an old password is
    46  	// specified, or when bootstrapping.
    47  	StateInfo *state.Info `yaml:",omitempty"`
    48  
    49  	// OldAPIPassword specifies a password that should
    50  	// be used to connect to the API if APIInfo.Password
    51  	// is blank or invalid.
    52  	OldAPIPassword string
    53  
    54  	// APIInfo specifies how the agent should connect to the
    55  	// state through the API.
    56  	APIInfo *api.Info `yaml:",omitempty"`
    57  }
    58  
    59  // Ensure that the formatter_1_12 struct implements the formatter interface.
    60  var _ formatter = (*formatter_1_12)(nil)
    61  
    62  func (*formatter_1_12) configFile(dirName string) string {
    63  	return path.Join(dirName, "agent.conf")
    64  }
    65  
    66  func (formatter *formatter_1_12) read(dirName string) (*configInternal, error) {
    67  	data, err := ioutil.ReadFile(formatter.configFile(dirName))
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  	var conf format_1_12Serialization
    72  	if err := goyaml.Unmarshal(data, &conf); err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	var stateDetails *connectionDetails
    77  	var caCert []byte
    78  	var tag string
    79  	if conf.StateInfo != nil {
    80  		stateDetails = &connectionDetails{
    81  			conf.StateInfo.Addrs,
    82  			conf.StateInfo.Password,
    83  		}
    84  		tag = conf.StateInfo.Tag
    85  		caCert = conf.StateInfo.CACert
    86  	}
    87  	var apiDetails *connectionDetails
    88  	if conf.APIInfo != nil {
    89  		apiDetails = &connectionDetails{
    90  			conf.APIInfo.Addrs,
    91  			conf.APIInfo.Password,
    92  		}
    93  		tag = conf.APIInfo.Tag
    94  		caCert = conf.APIInfo.CACert
    95  	}
    96  	return &configInternal{
    97  		tag:             tag,
    98  		nonce:           conf.MachineNonce,
    99  		caCert:          caCert,
   100  		stateDetails:    stateDetails,
   101  		apiDetails:      apiDetails,
   102  		oldPassword:     conf.OldPassword,
   103  		stateServerCert: conf.StateServerCert,
   104  		stateServerKey:  conf.StateServerKey,
   105  		apiPort:         conf.APIPort,
   106  		values:          map[string]string{},
   107  	}, nil
   108  }
   109  
   110  func (formatter *formatter_1_12) makeAgentConf(config *configInternal) *format_1_12Serialization {
   111  	format := &format_1_12Serialization{
   112  		StateServerCert: config.stateServerCert,
   113  		StateServerKey:  config.stateServerKey,
   114  		APIPort:         config.apiPort,
   115  		OldPassword:     config.oldPassword,
   116  		MachineNonce:    config.nonce,
   117  	}
   118  	if config.stateDetails != nil {
   119  		// It is fine that we are copying the slices for the addresses.
   120  		format.StateInfo = &state.Info{
   121  			Addrs:    config.stateDetails.addresses,
   122  			Password: config.stateDetails.password,
   123  			Tag:      config.tag,
   124  			CACert:   config.caCert,
   125  		}
   126  	}
   127  	if config.apiDetails != nil {
   128  		format.APIInfo = &api.Info{
   129  			Addrs:    config.apiDetails.addresses,
   130  			Password: config.apiDetails.password,
   131  			Tag:      config.tag,
   132  			CACert:   config.caCert,
   133  		}
   134  	}
   135  	return format
   136  }
   137  
   138  func (formatter *formatter_1_12) write(config *configInternal) error {
   139  	dirName := config.Dir()
   140  	conf := formatter.makeAgentConf(config)
   141  	data, err := goyaml.Marshal(conf)
   142  	if err != nil {
   143  		return err
   144  	}
   145  	if err := os.MkdirAll(dirName, 0755); err != nil {
   146  		return err
   147  	}
   148  	newFile := path.Join(dirName, "agent.conf-new")
   149  	if err := ioutil.WriteFile(newFile, data, 0600); err != nil {
   150  		return err
   151  	}
   152  	if err := os.Rename(newFile, formatter.configFile(dirName)); err != nil {
   153  		return err
   154  	}
   155  	return nil
   156  }
   157  
   158  func (formatter *formatter_1_12) writeCommands(config *configInternal) ([]string, error) {
   159  	dirName := config.Dir()
   160  	conf := formatter.makeAgentConf(config)
   161  	data, err := goyaml.Marshal(conf)
   162  	if err != nil {
   163  		return nil, err
   164  	}
   165  	var commands []string
   166  	addCommand := func(f string, a ...interface{}) {
   167  		commands = append(commands, fmt.Sprintf(f, a...))
   168  	}
   169  	filename := utils.ShQuote(formatter.configFile(dirName))
   170  	addCommand("mkdir -p %s", utils.ShQuote(dirName))
   171  	addCommand("install -m %o /dev/null %s", 0600, filename)
   172  	addCommand(`printf '%%s\n' %s > %s`, utils.ShQuote(string(data)), filename)
   173  	return commands, nil
   174  }
   175  
   176  func (*formatter_1_12) migrate(config *configInternal) {
   177  }