github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/state/apiserver/rsyslog/rsyslog.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package rsyslog
     5  
     6  import (
     7  	"github.com/juju/juju/cert"
     8  	"github.com/juju/juju/state"
     9  	"github.com/juju/juju/state/api/params"
    10  	"github.com/juju/juju/state/apiserver/common"
    11  	"github.com/juju/juju/state/watcher"
    12  )
    13  
    14  // RsyslogAPI implements the API used by the rsyslog worker.
    15  type RsyslogAPI struct {
    16  	*common.EnvironWatcher
    17  
    18  	st             *state.State
    19  	resources      *common.Resources
    20  	authorizer     common.Authorizer
    21  	StateAddresser *common.StateAddresser
    22  	canModify      bool
    23  }
    24  
    25  // NewRsyslogAPI creates a new instance of the Rsyslog API.
    26  func NewRsyslogAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*RsyslogAPI, error) {
    27  	if !authorizer.AuthMachineAgent() && !authorizer.AuthUnitAgent() {
    28  		return nil, common.ErrPerm
    29  	}
    30  	// Can always watch for environ changes.
    31  	getCanWatch := common.AuthAlways(true)
    32  	// Does not get the secrets.
    33  	getCanReadSecrets := common.AuthAlways(false)
    34  	return &RsyslogAPI{
    35  		EnvironWatcher: common.NewEnvironWatcher(st, resources, getCanWatch, getCanReadSecrets),
    36  		st:             st,
    37  		authorizer:     authorizer,
    38  		resources:      resources,
    39  		canModify:      authorizer.AuthEnvironManager(),
    40  		StateAddresser: common.NewStateAddresser(st),
    41  	}, nil
    42  }
    43  
    44  // SetRsyslogCert sets the rsyslog CACert.
    45  func (api *RsyslogAPI) SetRsyslogCert(args params.SetRsyslogCertParams) (params.ErrorResult, error) {
    46  	var result params.ErrorResult
    47  	if !api.canModify {
    48  		result.Error = common.ServerError(common.ErrBadCreds)
    49  		return result, nil
    50  	}
    51  	if _, err := cert.ParseCert(string(args.CACert)); err != nil {
    52  		result.Error = common.ServerError(err)
    53  		return result, nil
    54  	}
    55  	attrs := map[string]interface{}{"rsyslog-ca-cert": string(args.CACert)}
    56  	if err := api.st.UpdateEnvironConfig(attrs, nil, nil); err != nil {
    57  		result.Error = common.ServerError(err)
    58  	}
    59  	return result, nil
    60  }
    61  
    62  // GetRsyslogConfig returns a RsyslogConfigResult.
    63  func (api *RsyslogAPI) GetRsyslogConfig(args params.Entities) (params.RsyslogConfigResults, error) {
    64  	result := params.RsyslogConfigResults{
    65  		Results: make([]params.RsyslogConfigResult, len(args.Entities)),
    66  	}
    67  	cfg, err := api.st.EnvironConfig()
    68  	if err != nil {
    69  		return result, err
    70  	}
    71  	for i := range args.Entities {
    72  		rsyslogCfg, err := newRsyslogConfig(cfg, api)
    73  		if err == nil {
    74  			result.Results[i] = params.RsyslogConfigResult{
    75  				CACert:    rsyslogCfg.CACert,
    76  				Port:      rsyslogCfg.Port,
    77  				HostPorts: rsyslogCfg.HostPorts,
    78  			}
    79  		} else {
    80  			result.Results[i].Error = common.ServerError(err)
    81  		}
    82  	}
    83  	return result, nil
    84  }
    85  
    86  // WatchForRsyslogChanges starts a watcher to track if there are changes
    87  // that require we update the rsyslog.d configurations for a machine and/or unit.
    88  func (api *RsyslogAPI) WatchForRsyslogChanges(args params.Entities) (params.NotifyWatchResults, error) {
    89  	result := params.NotifyWatchResults{
    90  		Results: make([]params.NotifyWatchResult, len(args.Entities)),
    91  	}
    92  	for i := range args.Entities {
    93  		err := common.ErrPerm
    94  		if api.authorizer.AuthMachineAgent() || api.authorizer.AuthUnitAgent() {
    95  			watch := api.st.WatchAPIHostPorts()
    96  			// Consume the initial event. Technically, API
    97  			// calls to Watch 'transmit' the initial event
    98  			// in the Watch response. But NotifyWatchers
    99  			// have no state to transmit.
   100  			if _, ok := <-watch.Changes(); ok {
   101  				result.Results[i].NotifyWatcherId = api.resources.Register(watch)
   102  				err = nil
   103  			} else {
   104  				err = watcher.MustErr(watch)
   105  			}
   106  		}
   107  		result.Results[i].Error = common.ServerError(err)
   108  	}
   109  	return result, nil
   110  
   111  }