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  }