github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/client/cloud/instance_information.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package cloud
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"gopkg.in/juju/names.v2"
     9  
    10  	"github.com/juju/juju/apiserver/common"
    11  	"github.com/juju/juju/apiserver/params"
    12  	"github.com/juju/juju/core/constraints"
    13  	"github.com/juju/juju/environs"
    14  	"github.com/juju/juju/state/stateenvirons"
    15  )
    16  
    17  // EnvironConfigGetter implements environs.EnvironConfigGetter
    18  // in terms of a *state.State.
    19  type cloudEnvironConfigGetter struct {
    20  	Backend
    21  	region string
    22  }
    23  
    24  // CloudSpec implements environs.EnvironConfigGetter.
    25  func (g cloudEnvironConfigGetter) CloudSpec() (environs.CloudSpec, error) {
    26  	model, err := g.Model()
    27  	if err != nil {
    28  		return environs.CloudSpec{}, errors.Trace(err)
    29  	}
    30  	cloudName := model.Cloud()
    31  	regionName := g.region
    32  	credentialTag, _ := model.CloudCredential()
    33  	return stateenvirons.CloudSpec(g.Backend, cloudName, regionName, credentialTag)
    34  }
    35  
    36  // InstanceTypes returns instance type information for the cloud and region
    37  // in which the current model is deployed.
    38  func (api *CloudAPI) InstanceTypes(cons params.CloudInstanceTypesConstraints) (params.InstanceTypesResults, error) {
    39  	return instanceTypes(api, environs.GetEnviron, cons)
    40  }
    41  
    42  type environGetFunc func(st environs.EnvironConfigGetter, newEnviron environs.NewEnvironFunc) (environs.Environ, error)
    43  
    44  func instanceTypes(api *CloudAPI,
    45  	environGet environGetFunc,
    46  	cons params.CloudInstanceTypesConstraints,
    47  ) (params.InstanceTypesResults, error) {
    48  	m, err := api.ctlrBackend.Model()
    49  	if err != nil {
    50  		return params.InstanceTypesResults{}, errors.Trace(err)
    51  	}
    52  
    53  	result := make([]params.InstanceTypesResult, len(cons.Constraints))
    54  	// TODO(perrito666) Cache the results to avoid excessive querying of the cloud.
    55  	// TODO(perrito666) Add Region<>Cloud validation.
    56  	for i, cons := range cons.Constraints {
    57  		value := constraints.Value{}
    58  		if cons.Constraints != nil {
    59  			value = *cons.Constraints
    60  		}
    61  		backend := cloudEnvironConfigGetter{
    62  			Backend: api.backend,
    63  			region:  cons.CloudRegion,
    64  		}
    65  		cloudTag, err := names.ParseCloudTag(cons.CloudTag)
    66  		if err != nil {
    67  			result[i] = params.InstanceTypesResult{Error: common.ServerError(err)}
    68  			continue
    69  		}
    70  		if m.Cloud() != cloudTag.Id() {
    71  			result[i] = params.InstanceTypesResult{Error: common.ServerError(errors.NotValidf("asking %s cloud information to %s cloud", cloudTag.Id(), m.Cloud()))}
    72  			continue
    73  		}
    74  
    75  		env, err := environGet(backend, environs.New)
    76  		if err != nil {
    77  			return params.InstanceTypesResults{}, errors.Trace(err)
    78  		}
    79  
    80  		itCons := common.NewInstanceTypeConstraints(
    81  			env,
    82  			api.callContext,
    83  			value,
    84  		)
    85  		it, err := common.InstanceTypes(itCons)
    86  		if err != nil {
    87  			result[i] = params.InstanceTypesResult{Error: common.ServerError(err)}
    88  			continue
    89  		}
    90  		result[i] = it
    91  	}
    92  
    93  	return params.InstanceTypesResults{Results: result}, nil
    94  }