github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/controller/firewaller/machine.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package firewaller
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/names/v5"
    11  
    12  	apiwatcher "github.com/juju/juju/api/watcher"
    13  	"github.com/juju/juju/core/instance"
    14  	"github.com/juju/juju/core/life"
    15  	"github.com/juju/juju/core/network"
    16  	"github.com/juju/juju/core/watcher"
    17  	"github.com/juju/juju/rpc/params"
    18  )
    19  
    20  // Machine represents a juju machine as seen by the firewaller worker.
    21  type Machine struct {
    22  	st   *Client
    23  	tag  names.MachineTag
    24  	life life.Value
    25  }
    26  
    27  // Tag returns the machine tag.
    28  func (m *Machine) Tag() names.MachineTag {
    29  	return m.tag
    30  }
    31  
    32  // WatchUnits starts a StringsWatcher to watch all units assigned to
    33  // the machine.
    34  func (m *Machine) WatchUnits() (watcher.StringsWatcher, error) {
    35  	var results params.StringsWatchResults
    36  	args := params.Entities{
    37  		Entities: []params.Entity{{Tag: m.tag.String()}},
    38  	}
    39  	err := m.st.facade.FacadeCall("WatchUnits", args, &results)
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	if len(results.Results) != 1 {
    44  		return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results))
    45  	}
    46  	result := results.Results[0]
    47  	if result.Error != nil {
    48  		return nil, result.Error
    49  	}
    50  	w := apiwatcher.NewStringsWatcher(m.st.facade.RawAPICaller(), result)
    51  	return w, nil
    52  }
    53  
    54  // InstanceId returns the provider specific instance id for this
    55  // machine, or a CodeNotProvisioned error, if not set.
    56  func (m *Machine) InstanceId() (instance.Id, error) {
    57  	var results params.StringResults
    58  	args := params.Entities{
    59  		Entities: []params.Entity{{Tag: m.tag.String()}},
    60  	}
    61  	err := m.st.facade.FacadeCall("InstanceId", args, &results)
    62  	if err != nil {
    63  		return "", err
    64  	}
    65  	if len(results.Results) != 1 {
    66  		return "", fmt.Errorf("expected 1 result, got %d", len(results.Results))
    67  	}
    68  	result := results.Results[0]
    69  	if result.Error != nil {
    70  		if params.IsCodeNotProvisioned(result.Error) {
    71  			return "", errors.NotProvisionedf("machine %v", m.tag.Id())
    72  		}
    73  		return "", result.Error
    74  	}
    75  	return instance.Id(result.Result), nil
    76  }
    77  
    78  // Life returns the machine's life cycle value.
    79  func (m *Machine) Life() life.Value {
    80  	return m.life
    81  }
    82  
    83  // IsManual returns true if the machine was manually provisioned.
    84  func (m *Machine) IsManual() (bool, error) {
    85  	var results params.BoolResults
    86  	args := params.Entities{
    87  		Entities: []params.Entity{{Tag: m.tag.String()}},
    88  	}
    89  	err := m.st.facade.FacadeCall("AreManuallyProvisioned", args, &results)
    90  	if err != nil {
    91  		return false, err
    92  	}
    93  	if len(results.Results) != 1 {
    94  		return false, fmt.Errorf("expected 1 result, got %d", len(results.Results))
    95  	}
    96  	result := results.Results[0]
    97  	if result.Error != nil {
    98  		return false, result.Error
    99  	}
   100  	return result.Result, nil
   101  }
   102  
   103  // OpenedMachinePortRanges queries the open port ranges for all units on this
   104  // machine and returns back two maps where keys are unit names and values are
   105  // open port range groupings by subnet CIDR and endpoint name.
   106  func (m *Machine) OpenedMachinePortRanges() (byUnitAndCIDR map[names.UnitTag]network.GroupedPortRanges, byUnitAndEndpoint map[names.UnitTag]network.GroupedPortRanges, err error) {
   107  	var results params.OpenMachinePortRangesResults
   108  	args := params.Entities{
   109  		Entities: []params.Entity{{Tag: m.tag.String()}},
   110  	}
   111  	if err = m.st.facade.FacadeCall("OpenedMachinePortRanges", args, &results); err != nil {
   112  		return nil, nil, err
   113  	}
   114  	if len(results.Results) != 1 {
   115  		return nil, nil, fmt.Errorf("expected 1 result, got %d", len(results.Results))
   116  	}
   117  	result := results.Results[0]
   118  	if result.Error != nil {
   119  		return nil, nil, result.Error
   120  	}
   121  
   122  	byUnitAndCIDR = make(map[names.UnitTag]network.GroupedPortRanges)
   123  	byUnitAndEndpoint = make(map[names.UnitTag]network.GroupedPortRanges)
   124  	for unitTagStr, unitPortRangeList := range result.UnitPortRanges {
   125  		unitTag, err := names.ParseUnitTag(unitTagStr)
   126  		if err != nil {
   127  			return nil, nil, errors.Trace(err)
   128  		}
   129  
   130  		byUnitAndCIDR[unitTag] = make(network.GroupedPortRanges)
   131  		byUnitAndEndpoint[unitTag] = make(network.GroupedPortRanges)
   132  
   133  		for _, unitPortRanges := range unitPortRangeList {
   134  			portList := make([]network.PortRange, len(unitPortRanges.PortRanges))
   135  			for i, pr := range unitPortRanges.PortRanges {
   136  				portList[i] = pr.NetworkPortRange()
   137  			}
   138  
   139  			byUnitAndEndpoint[unitTag][unitPortRanges.Endpoint] = append(byUnitAndEndpoint[unitTag][unitPortRanges.Endpoint], portList...)
   140  			for _, cidr := range unitPortRanges.SubnetCIDRs {
   141  				byUnitAndCIDR[unitTag][cidr] = append(byUnitAndCIDR[unitTag][cidr], portList...)
   142  			}
   143  		}
   144  	}
   145  	return byUnitAndCIDR, byUnitAndEndpoint, nil
   146  }