launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/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 "launchpad.net/juju-core/environs" 8 "launchpad.net/juju-core/state" 9 "launchpad.net/juju-core/state/api/params" 10 "launchpad.net/juju-core/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 func (e *EnvironWatcher) WatchForEnvironConfigChanges() (params.NotifyWatchResult, error) { 40 result := params.NotifyWatchResult{} 41 42 canWatch, err := e.getCanWatch() 43 if err != nil { 44 return result, mask(err) 45 } 46 47 // TODO(dimitern) If we have multiple environments in state, use a 48 // tag argument here and as a method argument. 49 if !canWatch("") { 50 result.Error = ServerError(ErrPerm) 51 return result, ErrPerm 52 } 53 54 watch := e.st.WatchForEnvironConfigChanges() 55 // Consume the initial event. Technically, API 56 // calls to Watch 'transmit' the initial event 57 // in the Watch response. But NotifyWatchers 58 // have no state to transmit. 59 if _, ok := <-watch.Changes(); ok { 60 result.NotifyWatcherId = e.resources.Register(watch) 61 } else { 62 return result, watcher.MustErr(watch) 63 } 64 return result, nil 65 } 66 67 // EnvironConfig returns the current environment's configuration. 68 func (e *EnvironWatcher) EnvironConfig() (params.EnvironConfigResult, error) { 69 result := params.EnvironConfigResult{} 70 71 canReadSecrets, err := e.getCanReadSecrets() 72 if err != nil { 73 return result, mask(err) 74 } 75 76 config, err := e.st.EnvironConfig() 77 if err != nil { 78 return result, mask(err) 79 } 80 allAttrs := config.AllAttrs() 81 82 // TODO(dimitern) If we have multiple environments in state, use a 83 // tag argument here and as a method argument. 84 if !canReadSecrets("") { 85 // Mask out any secrets in the environment configuration 86 // with values of the same type, so it'll pass validation. 87 // 88 // TODO(dimitern) 201309-26 bug #1231384 89 // Delete the code below and mark the bug as fixed, 90 // once it's live tested on MAAS and 1.16 compatibility 91 // is dropped. 92 env, err := environs.New(config) 93 if err != nil { 94 return result, mask(err) 95 } 96 secretAttrs, err := env.Provider().SecretAttrs(config) 97 for k := range secretAttrs { 98 allAttrs[k] = "not available" 99 } 100 } 101 result.Config = allAttrs 102 return result, nil 103 }