github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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/base" 13 "github.com/juju/juju/apiserver/common" 14 "github.com/juju/juju/apiserver/facade" 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/status" 24 "github.com/juju/juju/state" 25 unitercontext "github.com/juju/juju/worker/uniter/runner/context" 26 "github.com/juju/juju/worker/uniter/runner/jujuc" 27 ) 28 29 const payloadsHookContextFacade = "PayloadsHookContext" 30 31 type payloads struct{} 32 33 func (c payloads) registerForServer() error { 34 c.registerPublicFacade() 35 c.registerHookContext() 36 return nil 37 } 38 39 func (c payloads) registerForClient() error { 40 c.registerPublicCommands() 41 return nil 42 } 43 44 func (payloads) newPublicFacade(st *state.State, resources facade.Resources, authorizer facade.Authorizer) (*server.PublicAPI, error) { 45 up, err := st.ModelPayloads() 46 if err != nil { 47 return nil, errors.Trace(err) 48 } 49 return server.NewPublicAPI(up), nil 50 } 51 52 func (c payloads) registerPublicFacade() { 53 if !markRegistered(payload.ComponentName, "public-facade") { 54 return 55 } 56 57 // NOTE: facade is also defined in api/facadeversions.go. 58 const version = 1 59 common.RegisterStandardFacade( 60 payload.FacadeName, 61 version, 62 c.newPublicFacade, 63 ) 64 } 65 66 type facadeCaller struct { 67 base.FacadeCaller 68 closeFunc func() error 69 } 70 71 func (c facadeCaller) Close() error { 72 return c.closeFunc() 73 } 74 75 func (payloads) newListAPIClient(cmd *status.ListCommand) (status.ListAPI, error) { 76 apiCaller, err := cmd.NewAPIRoot() 77 if err != nil { 78 return nil, errors.Trace(err) 79 } 80 caller := base.NewFacadeCallerForVersion(apiCaller, payload.FacadeName, 1) 81 82 listAPI := client.NewPublicClient(&facadeCaller{ 83 FacadeCaller: caller, 84 closeFunc: apiCaller.Close, 85 }) 86 return listAPI, nil 87 } 88 89 func (c payloads) registerPublicCommands() { 90 if !markRegistered(payload.ComponentName, "public-commands") { 91 return 92 } 93 94 commands.RegisterEnvCommand(func() modelcmd.ModelCommand { 95 return status.NewListCommand(c.newListAPIClient) 96 }) 97 } 98 99 func (c payloads) registerHookContext() { 100 if !markRegistered(payload.ComponentName, "hook-context") { 101 return 102 } 103 104 unitercontext.RegisterComponentFunc(payload.ComponentName, 105 func(config unitercontext.ComponentConfig) (jujuc.ContextComponent, error) { 106 hctxClient := c.newUnitFacadeClient(config.APICaller) 107 // TODO(ericsnow) Pass the unit's tag through to the component? 108 component, err := context.NewContextAPI(hctxClient, config.DataDir) 109 if err != nil { 110 return nil, errors.Trace(err) 111 } 112 return component, nil 113 }, 114 ) 115 116 c.registerHookContextCommands() 117 c.registerHookContextFacade() 118 } 119 120 func (payloads) newUnitFacadeClient(caller base.APICaller) context.APIClient { 121 facadeCaller := base.NewFacadeCallerForVersion(caller, payloadsHookContextFacade, 1) 122 return internalclient.NewUnitFacadeClient(facadeCaller) 123 } 124 125 func (payloads) newHookContextFacade(st *state.State, unit *state.Unit) (interface{}, error) { 126 up, err := st.UnitPayloads(unit) 127 if err != nil { 128 return nil, errors.Trace(err) 129 } 130 return internalserver.NewUnitFacade(up), nil 131 } 132 133 func (c payloads) registerHookContextFacade() { 134 const version = 1 135 common.RegisterHookContextFacade( 136 payloadsHookContextFacade, 137 version, 138 c.newHookContextFacade, 139 reflect.TypeOf(&internalserver.UnitFacade{}), 140 ) 141 } 142 143 type payloadsHookContext struct { 144 jujuc.Context 145 } 146 147 // Component implements context.HookContext. 148 func (c payloadsHookContext) Component(name string) (context.Component, error) { 149 found, err := c.Context.Component(name) 150 if err != nil { 151 return nil, errors.Trace(err) 152 } 153 compCtx, ok := found.(context.Component) 154 if !ok && found != nil { 155 return nil, errors.Errorf("wrong component context type registered: %T", found) 156 } 157 return compCtx, nil 158 } 159 160 func (payloads) registerHookContextCommands() { 161 if !markRegistered(payload.ComponentName, "hook-context-commands") { 162 return 163 } 164 165 jujuc.RegisterCommand(context.RegisterCmdName, func(ctx jujuc.Context) (cmd.Command, error) { 166 compCtx := payloadsHookContext{ctx} 167 cmd, err := context.NewRegisterCmd(compCtx) 168 if err != nil { 169 return nil, errors.Trace(err) 170 } 171 return cmd, nil 172 }) 173 174 jujuc.RegisterCommand(context.StatusSetCmdName, func(ctx jujuc.Context) (cmd.Command, error) { 175 compCtx := payloadsHookContext{ctx} 176 cmd, err := context.NewStatusSetCmd(compCtx) 177 if err != nil { 178 return nil, errors.Trace(err) 179 } 180 return cmd, nil 181 }) 182 183 jujuc.RegisterCommand(context.UnregisterCmdName, func(ctx jujuc.Context) (cmd.Command, error) { 184 compCtx := payloadsHookContext{ctx} 185 cmd, err := context.NewUnregisterCmd(compCtx) 186 if err != nil { 187 return nil, errors.Trace(err) 188 } 189 return cmd, nil 190 }) 191 }