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  }