github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/state/api/state.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package api 5 6 import ( 7 "net" 8 "strconv" 9 10 "github.com/juju/juju/network" 11 "github.com/juju/juju/state/api/agent" 12 "github.com/juju/juju/state/api/charmrevisionupdater" 13 "github.com/juju/juju/state/api/deployer" 14 "github.com/juju/juju/state/api/environment" 15 "github.com/juju/juju/state/api/firewaller" 16 "github.com/juju/juju/state/api/keyupdater" 17 apilogger "github.com/juju/juju/state/api/logger" 18 "github.com/juju/juju/state/api/machiner" 19 "github.com/juju/juju/state/api/networker" 20 "github.com/juju/juju/state/api/params" 21 "github.com/juju/juju/state/api/provisioner" 22 "github.com/juju/juju/state/api/rsyslog" 23 "github.com/juju/juju/state/api/uniter" 24 "github.com/juju/juju/state/api/upgrader" 25 ) 26 27 // Login authenticates as the entity with the given name and password. 28 // Subsequent requests on the state will act as that entity. This 29 // method is usually called automatically by Open. The machine nonce 30 // should be empty unless logging in as a machine agent. 31 func (st *State) Login(tag, password, nonce string) error { 32 var result params.LoginResult 33 err := st.Call("Admin", "", "Login", ¶ms.Creds{ 34 AuthTag: tag, 35 Password: password, 36 Nonce: nonce, 37 }, &result) 38 if err == nil { 39 st.authTag = tag 40 hostPorts, err := addAddress(result.Servers, st.addr) 41 if err != nil { 42 st.Close() 43 return err 44 } 45 st.hostPorts = hostPorts 46 st.environTag = result.EnvironTag 47 } 48 return err 49 } 50 51 // slideAddressToFront moves the address at the location (serverIndex, addrIndex) to be 52 // the first address of the first server. 53 func slideAddressToFront(servers [][]network.HostPort, serverIndex, addrIndex int) { 54 server := servers[serverIndex] 55 hostPort := server[addrIndex] 56 // Move the matching address to be the first in this server 57 for ; addrIndex > 0; addrIndex-- { 58 server[addrIndex] = server[addrIndex-1] 59 } 60 server[0] = hostPort 61 for ; serverIndex > 0; serverIndex-- { 62 servers[serverIndex] = servers[serverIndex-1] 63 } 64 servers[0] = server 65 } 66 67 // addAddress appends a new server derived from the given 68 // address to servers if the address is not already found 69 // there. 70 func addAddress(servers [][]network.HostPort, addr string) ([][]network.HostPort, error) { 71 for i, server := range servers { 72 for j, hostPort := range server { 73 if hostPort.NetAddr() == addr { 74 slideAddressToFront(servers, i, j) 75 return servers, nil 76 } 77 } 78 } 79 host, portString, err := net.SplitHostPort(addr) 80 if err != nil { 81 return nil, err 82 } 83 port, err := strconv.Atoi(portString) 84 if err != nil { 85 return nil, err 86 } 87 hostPort := network.HostPort{ 88 Address: network.NewAddress(host, network.ScopeUnknown), 89 Port: port, 90 } 91 result := make([][]network.HostPort, 0, len(servers)+1) 92 result = append(result, []network.HostPort{hostPort}) 93 result = append(result, servers...) 94 return result, nil 95 } 96 97 // Client returns an object that can be used 98 // to access client-specific functionality. 99 func (st *State) Client() *Client { 100 return &Client{st} 101 } 102 103 // Machiner returns a version of the state that provides functionality 104 // required by the machiner worker. 105 func (st *State) Machiner() *machiner.State { 106 return machiner.NewState(st) 107 } 108 109 // Networker returns a version of the state that provides functionality 110 // required by the networker worker. 111 func (st *State) Networker() *networker.State { 112 return networker.NewState(st) 113 } 114 115 // Provisioner returns a version of the state that provides functionality 116 // required by the provisioner worker. 117 func (st *State) Provisioner() *provisioner.State { 118 return provisioner.NewState(st) 119 } 120 121 // Uniter returns a version of the state that provides functionality 122 // required by the uniter worker. 123 func (st *State) Uniter() *uniter.State { 124 return uniter.NewState(st, st.authTag) 125 } 126 127 // Firewaller returns a version of the state that provides functionality 128 // required by the firewaller worker. 129 func (st *State) Firewaller() *firewaller.State { 130 return firewaller.NewState(st) 131 } 132 133 // Agent returns a version of the state that provides 134 // functionality required by the agent code. 135 func (st *State) Agent() *agent.State { 136 return agent.NewState(st) 137 } 138 139 // Upgrader returns access to the Upgrader API 140 func (st *State) Upgrader() *upgrader.State { 141 return upgrader.NewState(st) 142 } 143 144 // Deployer returns access to the Deployer API 145 func (st *State) Deployer() *deployer.State { 146 return deployer.NewState(st) 147 } 148 149 // Environment returns access to the Environment API 150 func (st *State) Environment() *environment.Facade { 151 return environment.NewFacade(st) 152 } 153 154 // Logger returns access to the Logger API 155 func (st *State) Logger() *apilogger.State { 156 return apilogger.NewState(st) 157 } 158 159 // KeyUpdater returns access to the KeyUpdater API 160 func (st *State) KeyUpdater() *keyupdater.State { 161 return keyupdater.NewState(st) 162 } 163 164 // CharmRevisionUpdater returns access to the CharmRevisionUpdater API 165 func (st *State) CharmRevisionUpdater() *charmrevisionupdater.State { 166 return charmrevisionupdater.NewState(st) 167 } 168 169 // Rsyslog returns access to the Rsyslog API 170 func (st *State) Rsyslog() *rsyslog.State { 171 return rsyslog.NewState(st) 172 }