github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/state/apiserver/common/environwatcher.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common 5 6 import ( 7 "github.com/juju/juju/environs" 8 "github.com/juju/juju/state" 9 "github.com/juju/juju/state/api/params" 10 "github.com/juju/juju/state/watcher" 11 ) 12 13 // EnvironWatcher implements two common methods for use by various 14 // facades - WatchForEnvironConfigChanges and EnvironConfig. 15 type EnvironWatcher struct { 16 st state.EnvironAccessor 17 resources *Resources 18 getCanWatch GetAuthFunc 19 getCanReadSecrets GetAuthFunc 20 } 21 22 // NewEnvironWatcher returns a new EnvironWatcher. Active watchers 23 // will be stored in the provided Resources. The two GetAuthFunc 24 // callbacks will be used on each invocation of the methods to 25 // determine current permissions. 26 // Right now, environment tags are not used, so both created AuthFuncs 27 // are called with "" for tag, which means "the current environment". 28 func NewEnvironWatcher(st state.EnvironAccessor, resources *Resources, getCanWatch, getCanReadSecrets GetAuthFunc) *EnvironWatcher { 29 return &EnvironWatcher{ 30 st: st, 31 resources: resources, 32 getCanWatch: getCanWatch, 33 getCanReadSecrets: getCanReadSecrets, 34 } 35 } 36 37 // WatchForEnvironConfigChanges returns a NotifyWatcher that observes 38 // changes to the environment configuration. 39 // Note that although the NotifyWatchResult contains an Error field, 40 // it's not used because we are only returning a single watcher, 41 // so we use the regular error return. 42 func (e *EnvironWatcher) WatchForEnvironConfigChanges() (params.NotifyWatchResult, error) { 43 result := params.NotifyWatchResult{} 44 45 canWatch, err := e.getCanWatch() 46 if err != nil { 47 return result, err 48 } 49 // TODO(dimitern) If we have multiple environments in state, use a 50 // tag argument here and as a method argument. 51 if !canWatch("") { 52 return result, ErrPerm 53 } 54 55 watch := e.st.WatchForEnvironConfigChanges() 56 // Consume the initial event. Technically, API 57 // calls to Watch 'transmit' the initial event 58 // in the Watch response. But NotifyWatchers 59 // have no state to transmit. 60 if _, ok := <-watch.Changes(); ok { 61 result.NotifyWatcherId = e.resources.Register(watch) 62 } else { 63 return result, watcher.MustErr(watch) 64 } 65 return result, nil 66 } 67 68 // EnvironConfig returns the current environment's configuration. 69 func (e *EnvironWatcher) EnvironConfig() (params.EnvironConfigResult, error) { 70 result := params.EnvironConfigResult{} 71 72 canReadSecrets, err := e.getCanReadSecrets() 73 if err != nil { 74 return result, err 75 } 76 77 config, err := e.st.EnvironConfig() 78 if err != nil { 79 return result, err 80 } 81 allAttrs := config.AllAttrs() 82 83 // TODO(dimitern) If we have multiple environments in state, use a 84 // tag argument here and as a method argument. 85 if !canReadSecrets("") { 86 // Mask out any secrets in the environment configuration 87 // with values of the same type, so it'll pass validation. 88 // 89 // TODO(dimitern) 201309-26 bug #1231384 90 // Delete the code below and mark the bug as fixed, 91 // once it's live tested on MAAS and 1.16 compatibility 92 // is dropped. 93 env, err := environs.New(config) 94 if err != nil { 95 return result, err 96 } 97 secretAttrs, err := env.Provider().SecretAttrs(config) 98 for k := range secretAttrs { 99 allAttrs[k] = "not available" 100 } 101 } 102 result.Config = allAttrs 103 return result, nil 104 }