launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/state/apiserver/common/tools.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  	errgo "launchpad.net/errgo/errors"
     8  	"launchpad.net/juju-core/environs"
     9  	"launchpad.net/juju-core/environs/config"
    10  	envtools "launchpad.net/juju-core/environs/tools"
    11  	"launchpad.net/juju-core/errors"
    12  	"launchpad.net/juju-core/state"
    13  	"launchpad.net/juju-core/state/api/params"
    14  	coretools "launchpad.net/juju-core/tools"
    15  	"launchpad.net/juju-core/version"
    16  )
    17  
    18  type EntityFinderEnvironConfigGetter interface {
    19  	state.EntityFinder
    20  	EnvironConfig() (*config.Config, error)
    21  }
    22  
    23  // ToolsGetter implements a common Tools method for use by various
    24  // facades.
    25  type ToolsGetter struct {
    26  	st         EntityFinderEnvironConfigGetter
    27  	getCanRead GetAuthFunc
    28  }
    29  
    30  // NewToolsGetter returns a new ToolsGetter. The GetAuthFunc will be
    31  // used on each invocation of Tools to determine current permissions.
    32  func NewToolsGetter(st EntityFinderEnvironConfigGetter, getCanRead GetAuthFunc) *ToolsGetter {
    33  	return &ToolsGetter{
    34  		st:         st,
    35  		getCanRead: getCanRead,
    36  	}
    37  }
    38  
    39  // Tools finds the tools necessary for the given agents.
    40  func (t *ToolsGetter) Tools(args params.Entities) (params.ToolsResults, error) {
    41  	result := params.ToolsResults{
    42  		Results: make([]params.ToolsResult, len(args.Entities)),
    43  	}
    44  	canRead, err := t.getCanRead()
    45  	if err != nil {
    46  		return result, mask(err)
    47  	}
    48  	agentVersion, cfg, err := t.getGlobalAgentVersion()
    49  	if err != nil {
    50  		return result, mask(err)
    51  	}
    52  
    53  	// SSLHostnameVerification defaults to true, so we need to
    54  	// invert that, for backwards-compatibility (older versions
    55  	// will have DisableSSLHostnameVerification: false by default).
    56  	disableSSLHostnameVerification := !cfg.SSLHostnameVerification()
    57  	env, err := environs.New(cfg)
    58  	if err != nil {
    59  		return result, mask(err)
    60  	}
    61  	for i, entity := range args.Entities {
    62  		agentTools, err := t.oneAgentTools(canRead, entity.Tag, agentVersion, env)
    63  		if err == nil {
    64  			result.Results[i].Tools = agentTools
    65  			result.Results[i].DisableSSLHostnameVerification = disableSSLHostnameVerification
    66  		}
    67  		result.Results[i].Error = ServerError(err)
    68  	}
    69  	return result, nil
    70  }
    71  
    72  func (t *ToolsGetter) getGlobalAgentVersion() (version.Number, *config.Config, error) {
    73  	// Get the Agent Version requested in the Environment Config
    74  	nothing := version.Number{}
    75  	cfg, err := t.st.EnvironConfig()
    76  	if err != nil {
    77  		return nothing, nil, mask(err)
    78  	}
    79  	agentVersion, ok := cfg.AgentVersion()
    80  	if !ok {
    81  		return nothing, nil, errgo.Newf("agent version not set in environment config")
    82  	}
    83  	return agentVersion, cfg, nil
    84  }
    85  
    86  func (t *ToolsGetter) oneAgentTools(canRead AuthFunc, tag string, agentVersion version.Number, env environs.Environ) (*coretools.Tools, error) {
    87  	if !canRead(tag) {
    88  		return nil, ErrPerm
    89  	}
    90  	entity, err := t.st.FindEntity(tag)
    91  	if err != nil {
    92  		return nil, mask(err, errors.IsNotFoundError)
    93  	}
    94  	tooler, ok := entity.(state.AgentTooler)
    95  	if !ok {
    96  		return nil, NotSupportedError(tag, "agent tools")
    97  	}
    98  	existingTools, err := tooler.AgentTools()
    99  	if err != nil {
   100  		return nil, mask(err)
   101  	}
   102  	// TODO(jam): Avoid searching the provider for every machine
   103  	// that wants to upgrade. The information could just be cached
   104  	// in state, or even in the API servers
   105  	return envtools.FindExactTools(env, agentVersion, existingTools.Version.Series, existingTools.Version.Arch)
   106  }