github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/component/all/payload.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package all 5 6 import ( 7 "reflect" 8 9 "github.com/juju/cmd" 10 "github.com/juju/errors" 11 12 "github.com/juju/juju/api" 13 "github.com/juju/juju/api/base" 14 "github.com/juju/juju/apiserver/common" 15 "github.com/juju/juju/cmd/juju/commands" 16 "github.com/juju/juju/cmd/modelcmd" 17 "github.com/juju/juju/payload" 18 "github.com/juju/juju/payload/api/client" 19 internalclient "github.com/juju/juju/payload/api/private/client" 20 internalserver "github.com/juju/juju/payload/api/private/server" 21 "github.com/juju/juju/payload/api/server" 22 "github.com/juju/juju/payload/context" 23 "github.com/juju/juju/payload/persistence" 24 payloadstate "github.com/juju/juju/payload/state" 25 "github.com/juju/juju/payload/status" 26 "github.com/juju/juju/state" 27 unitercontext "github.com/juju/juju/worker/uniter/runner/context" 28 "github.com/juju/juju/worker/uniter/runner/jujuc" 29 ) 30 31 const payloadsHookContextFacade = payload.ComponentName + "-hook-context" 32 33 type payloads struct{} 34 35 func (c payloads) registerForServer() error { 36 c.registerState() 37 c.registerPublicFacade() 38 39 c.registerHookContext() 40 41 return nil 42 } 43 44 func (c payloads) registerForClient() error { 45 c.registerPublicCommands() 46 return nil 47 } 48 49 func (payloads) newPublicFacade(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*server.PublicAPI, error) { 50 up, err := st.EnvPayloads() 51 if err != nil { 52 return nil, errors.Trace(err) 53 } 54 return server.NewPublicAPI(up), nil 55 } 56 57 func (c payloads) registerPublicFacade() { 58 if !markRegistered(payload.ComponentName, "public-facade") { 59 return 60 } 61 62 const version = 1 63 common.RegisterStandardFacade( 64 payload.ComponentName, 65 version, 66 c.newPublicFacade, 67 ) 68 api.RegisterFacadeVersion(payload.ComponentName, version) 69 } 70 71 type facadeCaller struct { 72 base.FacadeCaller 73 closeFunc func() error 74 } 75 76 func (c facadeCaller) Close() error { 77 return c.closeFunc() 78 } 79 80 func (payloads) newListAPIClient(cmd *status.ListCommand) (status.ListAPI, error) { 81 apiCaller, err := cmd.NewAPIRoot() 82 if err != nil { 83 return nil, errors.Trace(err) 84 } 85 caller := base.NewFacadeCallerForVersion(apiCaller, payload.ComponentName, 0) 86 87 listAPI := client.NewPublicClient(&facadeCaller{ 88 FacadeCaller: caller, 89 closeFunc: apiCaller.Close, 90 }) 91 return listAPI, nil 92 } 93 94 func (c payloads) registerPublicCommands() { 95 if !markRegistered(payload.ComponentName, "public-commands") { 96 return 97 } 98 99 commands.RegisterEnvCommand(func() modelcmd.ModelCommand { 100 return status.NewListCommand(c.newListAPIClient) 101 }) 102 } 103 104 func (c payloads) registerHookContext() { 105 if !markRegistered(payload.ComponentName, "hook-context") { 106 return 107 } 108 109 unitercontext.RegisterComponentFunc(payload.ComponentName, 110 func(config unitercontext.ComponentConfig) (jujuc.ContextComponent, error) { 111 hctxClient := c.newUnitFacadeClient(config.APICaller) 112 // TODO(ericsnow) Pass the unit's tag through to the component? 113 component, err := context.NewContextAPI(hctxClient, config.DataDir) 114 if err != nil { 115 return nil, errors.Trace(err) 116 } 117 return component, nil 118 }, 119 ) 120 121 c.registerHookContextCommands() 122 c.registerHookContextFacade() 123 } 124 125 func (payloads) newUnitFacadeClient(caller base.APICaller) context.APIClient { 126 facadeCaller := base.NewFacadeCallerForVersion(caller, payloadsHookContextFacade, 0) 127 return internalclient.NewUnitFacadeClient(facadeCaller) 128 } 129 130 func (payloads) newHookContextFacade(st *state.State, unit *state.Unit) (interface{}, error) { 131 up, err := st.UnitPayloads(unit) 132 if err != nil { 133 return nil, errors.Trace(err) 134 } 135 return internalserver.NewUnitFacade(up), nil 136 } 137 138 func (c payloads) registerHookContextFacade() { 139 const version = 0 140 common.RegisterHookContextFacade( 141 payloadsHookContextFacade, 142 version, 143 c.newHookContextFacade, 144 reflect.TypeOf(&internalserver.UnitFacade{}), 145 ) 146 api.RegisterFacadeVersion(payloadsHookContextFacade, version) 147 } 148 149 type payloadsHookContext struct { 150 jujuc.Context 151 } 152 153 // Component implements context.HookContext. 154 func (c payloadsHookContext) Component(name string) (context.Component, error) { 155 found, err := c.Context.Component(name) 156 if err != nil { 157 return nil, errors.Trace(err) 158 } 159 compCtx, ok := found.(context.Component) 160 if !ok && found != nil { 161 return nil, errors.Errorf("wrong component context type registered: %T", found) 162 } 163 return compCtx, nil 164 } 165 166 func (payloads) registerHookContextCommands() { 167 if !markRegistered(payload.ComponentName, "hook-context-commands") { 168 return 169 } 170 171 jujuc.RegisterCommand(context.RegisterCmdName, func(ctx jujuc.Context) (cmd.Command, error) { 172 compCtx := payloadsHookContext{ctx} 173 cmd, err := context.NewRegisterCmd(compCtx) 174 if err != nil { 175 return nil, errors.Trace(err) 176 } 177 return cmd, nil 178 }) 179 180 jujuc.RegisterCommand(context.StatusSetCmdName, func(ctx jujuc.Context) (cmd.Command, error) { 181 compCtx := payloadsHookContext{ctx} 182 cmd, err := context.NewStatusSetCmd(compCtx) 183 if err != nil { 184 return nil, errors.Trace(err) 185 } 186 return cmd, nil 187 }) 188 189 jujuc.RegisterCommand(context.UnregisterCmdName, func(ctx jujuc.Context) (cmd.Command, error) { 190 compCtx := payloadsHookContext{ctx} 191 cmd, err := context.NewUnregisterCmd(compCtx) 192 if err != nil { 193 return nil, errors.Trace(err) 194 } 195 return cmd, nil 196 }) 197 } 198 199 func (payloads) registerState() { 200 if !markRegistered(payload.ComponentName, "state") { 201 return 202 } 203 204 // TODO(ericsnow) Use a more general registration mechanism. 205 //state.RegisterMultiEnvCollections(persistence.Collections...) 206 207 newUnitPayloads := func(persist state.Persistence, unit, machine string) (state.UnitPayloads, error) { 208 return payloadstate.NewUnitPayloads(persist, unit, machine), nil 209 } 210 211 newEnvPayloads := func(persist state.PayloadsEnvPersistence) (state.EnvPayloads, error) { 212 envPersist := persistence.NewEnvPersistence(persist) 213 envPayloads := payloadstate.EnvPayloads{ 214 Persist: envPersist, 215 } 216 return envPayloads, nil 217 } 218 219 state.SetPayloadsComponent(newEnvPayloads, newUnitPayloads) 220 }