github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/agent/logger/logger.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package logger
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"gopkg.in/juju/names.v2"
     9  
    10  	"github.com/juju/juju/apiserver/common"
    11  	"github.com/juju/juju/apiserver/facade"
    12  	"github.com/juju/juju/apiserver/params"
    13  	"github.com/juju/juju/core/cache"
    14  	"github.com/juju/juju/environs/config"
    15  )
    16  
    17  // Logger defines the methods on the logger API end point.  Unfortunately, the
    18  // api infrastructure doesn't allow interfaces to be used as an actual
    19  // endpoint because our rpc mechanism panics.  However, I still feel that this
    20  // provides a useful documentation purpose.
    21  type Logger interface {
    22  	WatchLoggingConfig(args params.Entities) params.NotifyWatchResults
    23  	LoggingConfig(args params.Entities) params.StringResults
    24  }
    25  
    26  // LoggerAPI implements the Logger interface and is the concrete
    27  // implementation of the api end point.
    28  type LoggerAPI struct {
    29  	controller *cache.Controller
    30  	model      *cache.Model
    31  	resources  facade.Resources
    32  	authorizer facade.Authorizer
    33  }
    34  
    35  var _ Logger = (*LoggerAPI)(nil)
    36  
    37  // NewLoggerAPI creates a new server-side logger API end point.
    38  func NewLoggerAPI(ctx facade.Context) (*LoggerAPI, error) {
    39  	st := ctx.State()
    40  	resources := ctx.Resources()
    41  	authorizer := ctx.Auth()
    42  
    43  	if !authorizer.AuthMachineAgent() && !authorizer.AuthUnitAgent() && !authorizer.AuthApplicationAgent() {
    44  		return nil, common.ErrPerm
    45  	}
    46  	m, err := ctx.Controller().Model(st.ModelUUID())
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	return &LoggerAPI{
    52  		controller: ctx.Controller(),
    53  		model:      m,
    54  		resources:  resources,
    55  		authorizer: authorizer,
    56  	}, nil
    57  }
    58  
    59  // WatchLoggingConfig starts a watcher to track changes to the logging config
    60  // for the agents specified..  Unfortunately the current infrastruture makes
    61  // watching parts of the config non-trivial, so currently any change to the
    62  // config will cause the watcher to notify the client.
    63  func (api *LoggerAPI) WatchLoggingConfig(arg params.Entities) params.NotifyWatchResults {
    64  	result := make([]params.NotifyWatchResult, len(arg.Entities))
    65  	for i, entity := range arg.Entities {
    66  		tag, err := names.ParseTag(entity.Tag)
    67  		if err != nil {
    68  			result[i].Error = common.ServerError(err)
    69  			continue
    70  		}
    71  		err = common.ErrPerm
    72  		if api.authorizer.AuthOwner(tag) {
    73  			watch := api.model.WatchConfig("logging-config")
    74  			// Consume the initial event. Technically, API calls to Watch
    75  			// 'transmit' the initial event in the Watch response. But
    76  			// NotifyWatchers have no state to transmit.
    77  			if _, ok := <-watch.Changes(); ok {
    78  				result[i].NotifyWatcherId = api.resources.Register(watch)
    79  				err = nil
    80  			} else {
    81  				err = errors.New("programming error: channel should not be closed")
    82  			}
    83  		}
    84  		result[i].Error = common.ServerError(err)
    85  	}
    86  	return params.NotifyWatchResults{Results: result}
    87  }
    88  
    89  // LoggingConfig reports the logging configuration for the agents specified.
    90  func (api *LoggerAPI) LoggingConfig(arg params.Entities) params.StringResults {
    91  	if len(arg.Entities) == 0 {
    92  		return params.StringResults{}
    93  	}
    94  	results := make([]params.StringResult, len(arg.Entities))
    95  	// TODO: ensure that the cache model can return a proper config object.
    96  	config, configErr := config.New(config.NoDefaults, api.model.Config())
    97  	for i, entity := range arg.Entities {
    98  		tag, err := names.ParseTag(entity.Tag)
    99  		if err != nil {
   100  			results[i].Error = common.ServerError(err)
   101  			continue
   102  		}
   103  		err = common.ErrPerm
   104  		if api.authorizer.AuthOwner(tag) {
   105  			if configErr == nil {
   106  				results[i].Result = config.LoggingConfig()
   107  				err = nil
   108  			} else {
   109  				err = configErr
   110  			}
   111  		}
   112  		results[i].Error = common.ServerError(err)
   113  	}
   114  	return params.StringResults{Results: results}
   115  }