github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/common/cloudspec/statehelpers.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package cloudspec
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/names/v5"
     9  
    10  	environscloudspec "github.com/juju/juju/environs/cloudspec"
    11  	"github.com/juju/juju/state"
    12  	"github.com/juju/juju/state/stateenvirons"
    13  )
    14  
    15  // Pool describes an interface for retrieving State instances from a
    16  // collection.
    17  type Pool interface {
    18  	Get(string) (*state.PooledState, error)
    19  }
    20  
    21  // MakeCloudSpecGetter returns a function which returns a CloudSpec
    22  // for a given model, using the given Pool.
    23  func MakeCloudSpecGetter(pool Pool) func(names.ModelTag) (environscloudspec.CloudSpec, error) {
    24  	return func(tag names.ModelTag) (environscloudspec.CloudSpec, error) {
    25  		st, err := pool.Get(tag.Id())
    26  		if err != nil {
    27  			return environscloudspec.CloudSpec{}, errors.Trace(err)
    28  		}
    29  		defer st.Release()
    30  
    31  		m, err := st.Model()
    32  		if err != nil {
    33  			return environscloudspec.CloudSpec{}, errors.Trace(err)
    34  		}
    35  		// TODO - CAAS(externalreality): Once cloud methods are migrated
    36  		// to model EnvironConfigGetter will no longer need to contain
    37  		// both state and model but only model.
    38  		// TODO (manadart 2018-02-15): This potentially frees the state from
    39  		// the pool. Release is called, but the state reference survives.
    40  		return stateenvirons.EnvironConfigGetter{Model: m}.CloudSpec()
    41  	}
    42  }
    43  
    44  // MakeCloudSpecGetterForModel returns a function which returns a
    45  // CloudSpec for a single model. Attempts to request a CloudSpec for
    46  // any other model other than the one associated with the given
    47  // state.State results in an error.
    48  func MakeCloudSpecGetterForModel(st *state.State) func(names.ModelTag) (environscloudspec.CloudSpec, error) {
    49  	return func(tag names.ModelTag) (environscloudspec.CloudSpec, error) {
    50  		m, err := st.Model()
    51  		if err != nil {
    52  			return environscloudspec.CloudSpec{}, errors.Trace(err)
    53  		}
    54  		configGetter := stateenvirons.EnvironConfigGetter{Model: m}
    55  
    56  		if tag.Id() != st.ModelUUID() {
    57  			return environscloudspec.CloudSpec{}, errors.New("cannot get cloud spec for this model")
    58  		}
    59  		return configGetter.CloudSpec()
    60  	}
    61  }
    62  
    63  // MakeCloudSpecWatcherForModel returns a function which returns a
    64  // NotifyWatcher for cloud spec changes for a single model.
    65  // Attempts to request a watcher for any other model other than the
    66  // one associated with the given state.State results in an error.
    67  func MakeCloudSpecWatcherForModel(st *state.State) func(names.ModelTag) (state.NotifyWatcher, error) {
    68  	return func(tag names.ModelTag) (state.NotifyWatcher, error) {
    69  		m, err := st.Model()
    70  		if err != nil {
    71  			return nil, errors.Trace(err)
    72  		}
    73  		if tag.Id() != st.ModelUUID() {
    74  			return nil, errors.New("cannot get cloud spec for this model")
    75  		}
    76  		return m.WatchCloudSpecChanges(), nil
    77  	}
    78  }
    79  
    80  // MakeCloudSpecCredentialWatcherForModel returns a function which returns a
    81  // NotifyWatcher for changes to a model's credential reference.
    82  // This watch will detect when model's credential is replaced with another credential.
    83  // Attempts to request a watcher for any other model other than the
    84  // one associated with the given state.State results in an error.
    85  func MakeCloudSpecCredentialWatcherForModel(st *state.State) func(names.ModelTag) (state.NotifyWatcher, error) {
    86  	return func(tag names.ModelTag) (state.NotifyWatcher, error) {
    87  		m, err := st.Model()
    88  		if err != nil {
    89  			return nil, errors.Trace(err)
    90  		}
    91  		if tag.Id() != st.ModelUUID() {
    92  			return nil, errors.New("cannot get cloud spec credential for this model")
    93  		}
    94  		return m.WatchModelCredential(), nil
    95  	}
    96  }
    97  
    98  // MakeCloudSpecCredentialContentWatcherForModel returns a function which returns a
    99  // NotifyWatcher for credential content changes for a single model.
   100  // Attempts to request a watcher for any other model other than the
   101  // one associated with the given state.State results in an error.
   102  func MakeCloudSpecCredentialContentWatcherForModel(st *state.State) func(names.ModelTag) (state.NotifyWatcher, error) {
   103  	return func(tag names.ModelTag) (state.NotifyWatcher, error) {
   104  		m, err := st.Model()
   105  		if err != nil {
   106  			return nil, errors.Trace(err)
   107  		}
   108  		if tag.Id() != st.ModelUUID() {
   109  			return nil, errors.New("cannot get cloud spec credential content for this model")
   110  		}
   111  		credentialTag, exists := m.CloudCredentialTag()
   112  		if !exists {
   113  			return nil, nil
   114  		}
   115  		return st.WatchCredential(credentialTag), nil
   116  	}
   117  }