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