github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/apiserver/uniter/uniter_v1.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  // The uniter package implements the API interface used by the uniter
     5  // worker. This file contains the API facade version 1.
     6  package uniter
     7  
     8  import (
     9  	"github.com/juju/errors"
    10  	"github.com/juju/names"
    11  
    12  	"github.com/juju/juju/apiserver/common"
    13  	"github.com/juju/juju/apiserver/params"
    14  	"github.com/juju/juju/network"
    15  	"github.com/juju/juju/state"
    16  )
    17  
    18  func init() {
    19  	common.RegisterStandardFacade("Uniter", 1, NewUniterAPIV1)
    20  }
    21  
    22  // UniterAPI implements the API version 1, used by the uniter worker.
    23  type UniterAPIV1 struct {
    24  	uniterBaseAPI
    25  
    26  	accessMachine common.GetAuthFunc
    27  }
    28  
    29  // NewUniterAPIV1 creates a new instance of the Uniter API, version 1.
    30  func NewUniterAPIV1(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*UniterAPIV1, error) {
    31  	baseAPI, err := newUniterBaseAPI(st, resources, authorizer)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  	accessMachine := func() (common.AuthFunc, error) {
    36  		switch tag := authorizer.GetAuthTag().(type) {
    37  		case names.UnitTag:
    38  			entity, err := st.Unit(tag.Id())
    39  			if err != nil {
    40  				return nil, errors.Trace(err)
    41  			}
    42  			machineId, err := entity.AssignedMachineId()
    43  			if err != nil {
    44  				return nil, errors.Trace(err)
    45  			}
    46  			machineTag := names.NewMachineTag(machineId)
    47  			return func(tag names.Tag) bool {
    48  				return tag == machineTag
    49  			}, nil
    50  		default:
    51  			return nil, errors.Errorf("expected names.UnitTag, got %T", tag)
    52  		}
    53  	}
    54  	return &UniterAPIV1{
    55  		uniterBaseAPI: *baseAPI,
    56  
    57  		accessMachine: accessMachine,
    58  	}, nil
    59  }
    60  
    61  // AllMachinePorts returns all opened port ranges for each given
    62  // machine (on all networks).
    63  func (u *UniterAPIV1) AllMachinePorts(args params.Entities) (params.MachinePortsResults, error) {
    64  	result := params.MachinePortsResults{
    65  		Results: make([]params.MachinePortsResult, len(args.Entities)),
    66  	}
    67  	canAccess, err := u.accessMachine()
    68  	if err != nil {
    69  		return params.MachinePortsResults{}, err
    70  	}
    71  	for i, entity := range args.Entities {
    72  		result.Results[i] = u.getOneMachinePorts(canAccess, entity.Tag)
    73  	}
    74  	return result, nil
    75  }
    76  
    77  // ServiceOwner returns the owner user for each given service tag.
    78  func (u *UniterAPIV1) ServiceOwner(args params.Entities) (params.StringResults, error) {
    79  	result := params.StringResults{
    80  		Results: make([]params.StringResult, len(args.Entities)),
    81  	}
    82  	canAccess, err := u.accessService()
    83  	if err != nil {
    84  		return params.StringResults{}, err
    85  	}
    86  	for i, entity := range args.Entities {
    87  		tag, err := names.ParseServiceTag(entity.Tag)
    88  		if err != nil {
    89  			result.Results[i].Error = common.ServerError(common.ErrPerm)
    90  			continue
    91  		}
    92  		if !canAccess(tag) {
    93  			result.Results[i].Error = common.ServerError(common.ErrPerm)
    94  			continue
    95  		}
    96  		service, err := u.getService(tag)
    97  		if err != nil {
    98  			result.Results[i].Error = common.ServerError(err)
    99  			continue
   100  		}
   101  		result.Results[i].Result = service.GetOwnerTag()
   102  	}
   103  	return result, nil
   104  }
   105  
   106  // AssignedMachine returns the machine tag for each given unit tag, or
   107  // an error satisfying params.IsCodeNotAssigned when a unit has no
   108  // assigned machine.
   109  func (u *UniterAPIV1) AssignedMachine(args params.Entities) (params.StringResults, error) {
   110  	result := params.StringResults{
   111  		Results: make([]params.StringResult, len(args.Entities)),
   112  	}
   113  	canAccess, err := u.accessUnit()
   114  	if err != nil {
   115  		return params.StringResults{}, err
   116  	}
   117  	for i, entity := range args.Entities {
   118  		tag, err := names.ParseUnitTag(entity.Tag)
   119  		if err != nil {
   120  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   121  			continue
   122  		}
   123  		if !canAccess(tag) {
   124  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   125  			continue
   126  		}
   127  		unit, err := u.getUnit(tag)
   128  		if err != nil {
   129  			result.Results[i].Error = common.ServerError(err)
   130  			continue
   131  		}
   132  		machineId, err := unit.AssignedMachineId()
   133  		if err != nil {
   134  			result.Results[i].Error = common.ServerError(err)
   135  		} else {
   136  			result.Results[i].Result = names.NewMachineTag(machineId).String()
   137  		}
   138  	}
   139  	return result, nil
   140  }
   141  
   142  func (u *UniterAPIV1) getMachine(tag names.MachineTag) (*state.Machine, error) {
   143  	return u.st.Machine(tag.Id())
   144  }
   145  
   146  func (u *UniterAPIV1) getOneMachinePorts(canAccess common.AuthFunc, machineTag string) params.MachinePortsResult {
   147  	tag, err := names.ParseMachineTag(machineTag)
   148  	if err != nil {
   149  		return params.MachinePortsResult{Error: common.ServerError(common.ErrPerm)}
   150  	}
   151  	if !canAccess(tag) {
   152  		return params.MachinePortsResult{Error: common.ServerError(common.ErrPerm)}
   153  	}
   154  	machine, err := u.getMachine(tag)
   155  	if err != nil {
   156  		return params.MachinePortsResult{Error: common.ServerError(err)}
   157  	}
   158  	allPorts, err := machine.AllPorts()
   159  	if err != nil {
   160  		return params.MachinePortsResult{Error: common.ServerError(err)}
   161  	}
   162  	var resultPorts []params.MachinePortRange
   163  	for _, ports := range allPorts {
   164  		// AllPortRanges gives a map, but apis require a stable order
   165  		// for results, so sort the port ranges.
   166  		portRangesToUnits := ports.AllPortRanges()
   167  		portRanges := make([]network.PortRange, 0, len(portRangesToUnits))
   168  		for portRange := range portRangesToUnits {
   169  			portRanges = append(portRanges, portRange)
   170  		}
   171  		network.SortPortRanges(portRanges)
   172  		for _, portRange := range portRanges {
   173  			unitName := portRangesToUnits[portRange]
   174  			resultPorts = append(resultPorts, params.MachinePortRange{
   175  				UnitTag:   names.NewUnitTag(unitName).String(),
   176  				PortRange: params.FromNetworkPortRange(portRange),
   177  			})
   178  		}
   179  	}
   180  	return params.MachinePortsResult{
   181  		Ports: resultPorts,
   182  	}
   183  }