github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/state/stateenvirons/policy.go (about)

     1  // Copyright 2014, 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package stateenvirons
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/juju/caas"
     9  
    10  	"github.com/juju/juju/core/constraints"
    11  	"github.com/juju/juju/environs"
    12  	"github.com/juju/juju/environs/config"
    13  	"github.com/juju/juju/environs/context"
    14  	"github.com/juju/juju/state"
    15  	"github.com/juju/juju/storage"
    16  	"github.com/juju/juju/storage/provider"
    17  )
    18  
    19  // environStatePolicy implements state.Policy in
    20  // terms of environs.Environ and related types.
    21  type environStatePolicy struct {
    22  	st         *state.State
    23  	getEnviron NewEnvironFunc
    24  	getBroker  NewCAASBrokerFunc
    25  }
    26  
    27  // GetNewPolicyFunc returns a state.NewPolicyFunc that will return
    28  // a state.Policy implemented in terms of either environs.Environ
    29  // or caas.Broker and related types.
    30  func GetNewPolicyFunc() state.NewPolicyFunc {
    31  	return func(st *state.State) state.Policy {
    32  		return environStatePolicy{st, GetNewEnvironFunc(environs.New), GetNewCAASBrokerFunc(caas.New)}
    33  	}
    34  }
    35  
    36  // Prechecker implements state.Policy.
    37  func (p environStatePolicy) Prechecker() (environs.InstancePrechecker, error) {
    38  	model, err := p.st.Model()
    39  	if err != nil {
    40  		return nil, errors.Trace(err)
    41  	}
    42  	if model.Type() == state.ModelTypeIAAS {
    43  		return p.getEnviron(p.st)
    44  	}
    45  	return p.getBroker(p.st)
    46  }
    47  
    48  // ConfigValidator implements state.Policy.
    49  func (p environStatePolicy) ConfigValidator() (config.Validator, error) {
    50  	model, err := p.st.Model()
    51  	if err != nil {
    52  		return nil, errors.Trace(err)
    53  	}
    54  	if model.Type() != state.ModelTypeIAAS {
    55  		// TODO(caas) CAAS providers should also support
    56  		// config validation.
    57  		return nil, errors.NotImplementedf("ConfigValidator")
    58  	}
    59  	return environProvider(p.st)
    60  }
    61  
    62  // ProviderConfigSchemaSource implements state.Policy.
    63  func (p environStatePolicy) ProviderConfigSchemaSource() (config.ConfigSchemaSource, error) {
    64  	model, err := p.st.Model()
    65  	if err != nil {
    66  		return nil, errors.Trace(err)
    67  	}
    68  	if model.Type() != state.ModelTypeIAAS {
    69  		// TODO(caas) CAAS providers should also provide
    70  		// a config schema.
    71  		return nil, errors.NotImplementedf("ProviderConfigSchemaSource")
    72  	}
    73  	provider, err := environProvider(p.st)
    74  	if err != nil {
    75  		return nil, errors.Trace(err)
    76  	}
    77  	if cs, ok := provider.(config.ConfigSchemaSource); ok {
    78  		return cs, nil
    79  	}
    80  	return nil, errors.NotImplementedf("config.ConfigSource")
    81  }
    82  
    83  // ConstraintsValidator implements state.Policy.
    84  func (p environStatePolicy) ConstraintsValidator(ctx context.ProviderCallContext) (constraints.Validator, error) {
    85  	model, err := p.st.Model()
    86  	if err != nil {
    87  		return nil, errors.Trace(err)
    88  	}
    89  
    90  	if model.Type() == state.ModelTypeIAAS {
    91  		env, err := p.getEnviron(p.st)
    92  		if err != nil {
    93  			return nil, err
    94  		}
    95  		return env.ConstraintsValidator(ctx)
    96  	}
    97  	broker, err := p.getBroker(p.st)
    98  	if err != nil {
    99  		return nil, errors.Trace(err)
   100  	}
   101  	return broker.ConstraintsValidator(ctx)
   102  }
   103  
   104  // InstanceDistributor implements state.Policy.
   105  func (p environStatePolicy) InstanceDistributor() (context.Distributor, error) {
   106  	model, err := p.st.Model()
   107  	if err != nil {
   108  		return nil, errors.Trace(err)
   109  	}
   110  	if model.Type() != state.ModelTypeIAAS {
   111  		// Only IAAS models support machines, hence distribution.
   112  		return nil, errors.NotImplementedf("InstanceDistributor")
   113  	}
   114  	env, err := p.getEnviron(p.st)
   115  	if err != nil {
   116  		return nil, err
   117  	}
   118  	if p, ok := env.(context.Distributor); ok {
   119  		return p, nil
   120  	}
   121  	return nil, errors.NotImplementedf("InstanceDistributor")
   122  }
   123  
   124  // StorageProviderRegistry implements state.Policy.
   125  func (p environStatePolicy) StorageProviderRegistry() (storage.ProviderRegistry, error) {
   126  	model, err := p.st.Model()
   127  	if err != nil {
   128  		return nil, errors.Trace(err)
   129  	}
   130  	return NewStorageProviderRegistryForModel(model, p.getEnviron, p.getBroker)
   131  }
   132  
   133  // NewStorageProviderRegistryForModel returns a storage provider registry
   134  // for the specified model.
   135  func NewStorageProviderRegistryForModel(
   136  	model *state.Model,
   137  	newEnv NewEnvironFunc,
   138  	newBroker NewCAASBrokerFunc,
   139  ) (_ storage.ProviderRegistry, err error) {
   140  	var reg storage.ProviderRegistry
   141  	if model.Type() == state.ModelTypeIAAS {
   142  		if reg, err = newEnv(model.State()); err != nil {
   143  			return nil, errors.Trace(err)
   144  		}
   145  	} else {
   146  		if reg, err = newBroker(model.State()); err != nil {
   147  			return nil, errors.Trace(err)
   148  		}
   149  	}
   150  	return NewStorageProviderRegistry(reg), nil
   151  }
   152  
   153  // NewStorageProviderRegistry returns a storage.ProviderRegistry that chains
   154  // the provided registry with the common storage providers.
   155  func NewStorageProviderRegistry(reg storage.ProviderRegistry) storage.ProviderRegistry {
   156  	return storage.ChainedProviderRegistry{reg, provider.CommonStorageProviders()}
   157  }
   158  
   159  func environProvider(st *state.State) (environs.EnvironProvider, error) {
   160  	model, err := st.Model()
   161  	if err != nil {
   162  		return nil, errors.Annotate(err, "getting model")
   163  	}
   164  	cloud, err := st.Cloud(model.Cloud())
   165  	if err != nil {
   166  		return nil, errors.Annotate(err, "getting cloud")
   167  	}
   168  	// EnvironProvider implements state.ConfigValidator.
   169  	return environs.Provider(cloud.Type)
   170  }