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  }