github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/provider/ec2/subnet.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package ec2
     5  
     6  import (
     7  	"net"
     8  	"strings"
     9  
    10  	"github.com/aws/aws-sdk-go-v2/aws"
    11  	"github.com/aws/aws-sdk-go-v2/service/ec2/types"
    12  	"github.com/kr/pretty"
    13  )
    14  
    15  type SubnetMatcher interface {
    16  	Match(types.Subnet) bool
    17  }
    18  
    19  // CreateSubnetMatcher creates a SubnetMatcher that handles a particular method
    20  // of comparison based on the content of the subnet query. If the query looks
    21  // like a CIDR, then we will match subnets with the same CIDR. If it follows
    22  // the syntax of a "subnet-XXXX" then we will match the Subnet ID. Everything
    23  // else is just matched as a Name.
    24  func CreateSubnetMatcher(subnetQuery string) SubnetMatcher {
    25  	logger.Debugf("searching for subnet matching placement directive %q", subnetQuery)
    26  	_, ipNet, err := net.ParseCIDR(subnetQuery)
    27  	if err == nil {
    28  		return &cidrSubnetMatcher{
    29  			ipNet: ipNet,
    30  			CIDR:  ipNet.String(),
    31  		}
    32  	}
    33  	if strings.HasPrefix(subnetQuery, "subnet-") {
    34  		return &subnetIDMatcher{
    35  			subnetID: subnetQuery,
    36  		}
    37  	}
    38  	return &subnetNameMatcher{
    39  		name: subnetQuery,
    40  	}
    41  }
    42  
    43  type cidrSubnetMatcher struct {
    44  	ipNet *net.IPNet
    45  	CIDR  string
    46  }
    47  
    48  var _ SubnetMatcher = (*cidrSubnetMatcher)(nil)
    49  
    50  func (sm *cidrSubnetMatcher) Match(subnet types.Subnet) bool {
    51  	_, existingIPNet, err := net.ParseCIDR(aws.ToString(subnet.CidrBlock))
    52  	if err != nil {
    53  		logger.Debugf("subnet %s has invalid CIDRBlock", pretty.Sprint(subnet))
    54  		return false
    55  	}
    56  	if sm.CIDR == existingIPNet.String() {
    57  		logger.Debugf("found subnet %q by matching subnet CIDR: %s", aws.ToString(subnet.SubnetId), sm.CIDR)
    58  		return true
    59  	}
    60  	return false
    61  }
    62  
    63  type subnetIDMatcher struct {
    64  	subnetID string
    65  }
    66  
    67  func (sm *subnetIDMatcher) Match(subnet types.Subnet) bool {
    68  	if subnetID := aws.ToString(subnet.SubnetId); subnetID == sm.subnetID {
    69  		logger.Debugf("found subnet %q by ID", subnetID)
    70  		return true
    71  	}
    72  	return false
    73  }
    74  
    75  type subnetNameMatcher struct {
    76  	name string
    77  }
    78  
    79  func (sm *subnetNameMatcher) Match(subnet types.Subnet) bool {
    80  	for _, tag := range subnet.Tags {
    81  		if aws.ToString(tag.Key) == "Name" && aws.ToString(tag.Value) == sm.name {
    82  			logger.Debugf("found subnet %q matching name %q", aws.ToString(subnet.SubnetId), sm.name)
    83  			return true
    84  		}
    85  	}
    86  	return false
    87  }