github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/agent/format-1.16.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 "encoding/base64" 8 "fmt" 9 "net" 10 "strconv" 11 12 "github.com/juju/names" 13 goyaml "gopkg.in/yaml.v1" 14 15 "github.com/juju/juju/apiserver/params" 16 "github.com/juju/juju/version" 17 ) 18 19 var format_1_16 = formatter_1_16{} 20 21 // formatter_1_16 is the formatter for the 1.16 format. 22 type formatter_1_16 struct { 23 } 24 25 // Ensure that the formatter_1_16 struct implements the formatter interface. 26 var _ formatter = formatter_1_16{} 27 28 // format_1_16Serialization holds information for a given agent. 29 type format_1_16Serialization struct { 30 Tag string 31 Nonce string 32 UpgradedToVersion *version.Number `yaml:"upgradedToVersion"` 33 34 CACert string 35 StateAddresses []string `yaml:",omitempty"` 36 StatePassword string `yaml:",omitempty"` 37 38 APIAddresses []string `yaml:",omitempty"` 39 APIPassword string `yaml:",omitempty"` 40 41 OldPassword string 42 Values map[string]string 43 44 // Only state server machines have these next three items 45 StateServerCert string `yaml:",omitempty"` 46 StateServerKey string `yaml:",omitempty"` 47 APIPort int `yaml:",omitempty"` 48 } 49 50 func init() { 51 registerFormat(format_1_16) 52 } 53 54 const legacyFormatFilename = "format" 55 56 // legacyFormatPrefix is the prefix of the legacy format file. 57 const legacyFormatPrefix = "format " 58 59 // decode64 makes sure that for an empty string we have a nil slice, not an 60 // empty slice, which is what the base64 DecodeString function returns. 61 func decode64(value string) (result []byte, err error) { 62 if value != "" { 63 result, err = base64.StdEncoding.DecodeString(value) 64 } 65 return 66 } 67 68 func (formatter_1_16) version() string { 69 return "1.16" 70 } 71 72 func (formatter_1_16) unmarshal(data []byte) (*configInternal, error) { 73 var format format_1_16Serialization 74 if err := goyaml.Unmarshal(data, &format); err != nil { 75 return nil, err 76 } 77 caCert, err := decode64(format.CACert) 78 if err != nil { 79 return nil, err 80 } 81 stateServerCert, err := decode64(format.StateServerCert) 82 if err != nil { 83 return nil, err 84 } 85 stateServerKey, err := decode64(format.StateServerKey) 86 if err != nil { 87 return nil, err 88 } 89 if format.UpgradedToVersion == nil { 90 // Assume it's 1.16.0. 91 upgradedToVersion := version.MustParse("1.16.0") 92 format.UpgradedToVersion = &upgradedToVersion 93 } 94 tag, err := names.ParseTag(format.Tag) 95 if err != nil { 96 return nil, err 97 } 98 config := &configInternal{ 99 tag: tag, 100 nonce: format.Nonce, 101 dataDir: DefaultDataDir, 102 logDir: DefaultLogDir, 103 upgradedToVersion: *format.UpgradedToVersion, 104 caCert: string(caCert), 105 oldPassword: format.OldPassword, 106 values: format.Values, 107 } 108 if len(format.StateAddresses) > 0 { 109 config.stateDetails = &connectionDetails{ 110 format.StateAddresses, 111 format.StatePassword, 112 } 113 } 114 115 if len(stateServerKey) != 0 { 116 config.servingInfo = ¶ms.StateServingInfo{ 117 Cert: string(stateServerCert), 118 PrivateKey: string(stateServerKey), 119 APIPort: format.APIPort, 120 } 121 // There's a private key, then we need the state 122 // port, which wasn't directly available in the 1.16 format, 123 // but we can infer it from the ports in the state addresses. 124 if len(format.StateAddresses) > 0 { 125 _, portString, err := net.SplitHostPort(format.StateAddresses[0]) 126 if err != nil { 127 return nil, err 128 } 129 statePort, err := strconv.Atoi(portString) 130 if err != nil { 131 return nil, err 132 } 133 config.servingInfo.StatePort = statePort 134 } else { 135 return nil, fmt.Errorf("server key found but no state port") 136 } 137 } 138 if len(format.APIAddresses) > 0 { 139 config.apiDetails = &connectionDetails{ 140 format.APIAddresses, 141 format.APIPassword, 142 } 143 } 144 return config, nil 145 }