Use a StrEnum for cloud driver resource types

So that we can enumerate all of the resource types, switch these
constants to a StrEnum.  Later changes will use this to create
statsd gauges for each resource type.

Change-Id: I60235b77f078d4f7e404dd5eab3650dc896bd8f1
This commit is contained in:
James E. Blair
2026-06-26 08:27:44 -07:00
parent 6fae91b910
commit 67e7743e99
9 changed files with 69 additions and 51 deletions
+17 -15
View File
@@ -829,7 +829,7 @@ class AwsProviderEndpoint(BaseProviderEndpoint):
continue
tags = tag_list_to_dict(template.get('Tags', []))
yield AwsResource(tags,
AwsResource.TYPE_LAUNCH_TEMPLATE,
AwsResource.ResourceType.LAUNCH_TEMPLATE,
template_name)
def listResources(self, providers):
@@ -849,7 +849,7 @@ class AwsProviderEndpoint(BaseProviderEndpoint):
except botocore.exceptions.ClientError:
continue
yield AwsResource(tag_list_to_dict(host.get('Tags')),
AwsResource.TYPE_HOST,
AwsResource.ResourceType.HOST,
host['HostId'])
for instance in self._listInstances():
try:
@@ -858,7 +858,7 @@ class AwsProviderEndpoint(BaseProviderEndpoint):
except botocore.exceptions.ClientError:
continue
yield AwsResource(tag_list_to_dict(instance.get('Tags')),
AwsResource.TYPE_INSTANCE,
AwsResource.ResourceType.INSTANCE,
instance['InstanceId'])
for volume in self._listVolumes():
try:
@@ -867,7 +867,8 @@ class AwsProviderEndpoint(BaseProviderEndpoint):
except botocore.exceptions.ClientError:
continue
yield AwsResource(tag_list_to_dict(volume.get('Tags')),
AwsResource.TYPE_VOLUME, volume['VolumeId'])
AwsResource.ResourceType.VOLUME,
volume['VolumeId'])
for ami in self._listAmis():
try:
if ami['State'].lower() == "deleted":
@@ -875,7 +876,7 @@ class AwsProviderEndpoint(BaseProviderEndpoint):
except botocore.exceptions.ClientError:
continue
yield AwsResource(tag_list_to_dict(ami.get('Tags')),
AwsResource.TYPE_AMI, ami['ImageId'])
AwsResource.ResourceType.AMI, ami['ImageId'])
for snap in self._listSnapshots():
try:
if snap['State'].lower() == "deleted":
@@ -883,7 +884,8 @@ class AwsProviderEndpoint(BaseProviderEndpoint):
except botocore.exceptions.ClientError:
continue
yield AwsResource(tag_list_to_dict(snap.get('Tags')),
AwsResource.TYPE_SNAPSHOT, snap['SnapshotId'])
AwsResource.ResourceType.SNAPSHOT,
snap['SnapshotId'])
for bucket_name in bucket_names:
for obj in self._listObjects(bucket_name):
with self.non_mutating_rate_limiter:
@@ -893,28 +895,28 @@ class AwsProviderEndpoint(BaseProviderEndpoint):
except botocore.exceptions.ClientError:
continue
yield AwsResource(tag_list_to_dict(tags['TagSet']),
AwsResource.TYPE_OBJECT, obj.key,
AwsResource.ResourceType.OBJECT, obj.key,
bucket_name=bucket_name)
for template in self._listLaunchTemplates():
yield AwsResource(tag_list_to_dict(template.get('Tags')),
AwsResource.TYPE_LAUNCH_TEMPLATE,
AwsResource.ResourceType.LAUNCH_TEMPLATE,
template['LaunchTemplateName'])
def deleteResource(self, resource):
self.log.info(f"Deleting leaked {resource.type}: {resource.id}")
if resource.type == AwsResource.TYPE_HOST:
if resource.type == AwsResource.ResourceType.HOST:
self._releaseHost(resource.id, immediate=True)
if resource.type == AwsResource.TYPE_INSTANCE:
if resource.type == AwsResource.ResourceType.INSTANCE:
self._deleteInstance(resource.id, immediate=True)
if resource.type == AwsResource.TYPE_VOLUME:
if resource.type == AwsResource.ResourceType.VOLUME:
self._deleteVolume(resource.id)
if resource.type == AwsResource.TYPE_AMI:
if resource.type == AwsResource.ResourceType.AMI:
self._deleteAmi(resource.id)
if resource.type == AwsResource.TYPE_SNAPSHOT:
if resource.type == AwsResource.ResourceType.SNAPSHOT:
self._deleteSnapshot(resource.id)
if resource.type == AwsResource.TYPE_OBJECT:
if resource.type == AwsResource.ResourceType.OBJECT:
self._deleteObject(resource.bucket_name, resource.id)
if resource.type == AwsResource.TYPE_LAUNCH_TEMPLATE:
if resource.type == AwsResource.ResourceType.LAUNCH_TEMPLATE:
self._deleteLaunchTemplate(resource.id)
def listInstances(self):
+10 -7
View File
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from enum import StrEnum
from zuul import model
from zuul.provider import statemachine
from zuul.driver.aws.util import tag_list_to_dict
@@ -76,13 +78,14 @@ class AwsInstance(statemachine.Instance):
class AwsResource(statemachine.Resource):
TYPE_HOST = 'host'
TYPE_INSTANCE = 'instance'
TYPE_AMI = 'ami'
TYPE_SNAPSHOT = 'snapshot'
TYPE_VOLUME = 'volume'
TYPE_OBJECT = 'object'
TYPE_LAUNCH_TEMPLATE = 'launch-template'
class ResourceType(StrEnum):
HOST = 'host'
INSTANCE = 'instance'
AMI = 'ami'
SNAPSHOT = 'snapshot'
VOLUME = 'volume'
OBJECT = 'object'
LAUNCH_TEMPLATE = 'launch-template'
def __init__(self, metadata, type, id, bucket_name=None):
super().__init__(metadata, type)
+10 -10
View File
@@ -464,33 +464,33 @@ class AzureProviderEndpoint(BaseProviderEndpoint):
for vm in self._listVirtualMachines():
yield AzureResource(vm.get('tags', {}),
AzureResource.TYPE_INSTANCE,
AzureResource.ResourceType.INSTANCE,
vm['id'])
for nic in self._listNetworkInterfaces():
yield AzureResource(nic.get('tags', {}),
AzureResource.TYPE_NIC, nic['id'])
AzureResource.ResourceType.NIC, nic['id'])
for pip in self._listPublicIPAddresses():
yield AzureResource(pip.get('tags', {}),
AzureResource.TYPE_PIP, pip['id'])
AzureResource.ResourceType.PIP, pip['id'])
for disk in self._listDisks():
yield AzureResource(disk.get('tags', {}),
AzureResource.TYPE_DISK, disk['id'])
AzureResource.ResourceType.DISK, disk['id'])
for image in self._listImages():
yield AzureResource(image.get('tags', {}),
AzureResource.TYPE_IMAGE, image['id'])
AzureResource.ResourceType.IMAGE, image['id'])
def deleteResource(self, resource):
self.log.info("Deleting leaked %s: %s",
resource.type, resource.id)
if resource.type == AzureResource.TYPE_INSTANCE:
if resource.type == AzureResource.ResourceType.INSTANCE:
crud = self._client.virtual_machines
elif resource.type == AzureResource.TYPE_NIC:
elif resource.type == AzureResource.ResourceType.NIC:
crud = self._client.network_interfaces
elif resource.type == AzureResource.TYPE_PIP:
elif resource.type == AzureResource.ResourceType.PIP:
crud = self._client.public_ip_addresses
elif resource.type == AzureResource.TYPE_DISK:
elif resource.type == AzureResource.ResourceType.DISK:
crud = self._client.disks
elif resource.type == AzureResource.TYPE_IMAGE:
elif resource.type == AzureResource.ResourceType.IMAGE:
crud = self._client.images
with self.rate_limiter:
try:
+8 -5
View File
@@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from enum import StrEnum
from zuul import model
from zuul.provider import statemachine
@@ -72,11 +74,12 @@ class AzureInstance(statemachine.Instance):
class AzureResource(statemachine.Resource):
TYPE_INSTANCE = 'instance'
TYPE_NIC = 'nic'
TYPE_PIP = 'pip'
TYPE_DISK = 'disk'
TYPE_IMAGE = 'image'
class ResourceType(StrEnum):
INSTANCE = 'instance'
NIC = 'nic'
PIP = 'pip'
DISK = 'disk'
IMAGE = 'image'
def __init__(self, metadata, type, id):
super().__init__(metadata, type)
+4 -4
View File
@@ -199,10 +199,10 @@ class KubernetesProviderEndpoint(BaseProviderEndpoint):
projects = self.dynamic_client.resources.get(
api_version='v1', kind='Project')
namespaces = projects.get().items
namespace_type = KubernetesResource.TYPE_PROJECT
namespace_type = KubernetesResource.ResourceType.PROJECT
else:
namespaces = self.core_client.list_namespace().items
namespace_type = KubernetesResource.TYPE_NAMESPACE
namespace_type = KubernetesResource.ResourceType.NAMESPACE
for namespace in namespaces:
yield KubernetesResource(namespace.metadata.labels or {},
@@ -211,9 +211,9 @@ class KubernetesProviderEndpoint(BaseProviderEndpoint):
def deleteResource(self, resource):
self.log.info(f"Deleting leaked {resource.type}: {resource.id}")
if resource.type == KubernetesResource.TYPE_NAMESPACE:
if resource.type == KubernetesResource.ResourceType.NAMESPACE:
self._deleteNamespace(resource.id)
elif resource.type == KubernetesResource.TYPE_PROJECT:
elif resource.type == KubernetesResource.ResourceType.PROJECT:
self._deleteProject(resource.id)
def listInstances(self):
+5 -2
View File
@@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from enum import StrEnum
from zuul import model
from zuul.provider import statemachine
@@ -46,8 +48,9 @@ class KubernetesInstance(statemachine.Instance):
class KubernetesResource(statemachine.Resource):
TYPE_NAMESPACE = 'namespace'
TYPE_PROJECT = 'project'
class ResourceType(StrEnum):
NAMESPACE = 'namespace'
PROJECT = 'project'
def __init__(self, metadata, type, id):
super().__init__(metadata, type)
+2 -2
View File
@@ -485,7 +485,7 @@ class OpenstackProviderEndpoint(BaseProviderEndpoint):
if server['status'].lower() == 'deleted':
continue
yield OpenstackResource(server.get('metadata', {}),
OpenstackResource.TYPE_INSTANCE,
OpenstackResource.ResourceType.INSTANCE,
server['id'])
# Floating IP and port leakage can't be handled by the
# automatic resource cleanup in cleanupLeakedResources because
@@ -501,7 +501,7 @@ class OpenstackProviderEndpoint(BaseProviderEndpoint):
def deleteResource(self, resource):
self.log.info(f"Deleting leaked {resource.type}: {resource.id}")
if resource.type == OpenstackResource.TYPE_INSTANCE:
if resource.type == OpenstackResource.ResourceType.INSTANCE:
self._deleteServer(resource.id)
def listInstances(self):
+9 -6
View File
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from enum import StrEnum
from zuul import model
from zuul.provider import statemachine
@@ -57,12 +59,13 @@ class OpenstackInstance(statemachine.Instance):
class OpenstackResource(statemachine.Resource):
TYPE_HOST = 'host'
TYPE_INSTANCE = 'instance'
TYPE_AMI = 'ami'
TYPE_SNAPSHOT = 'snapshot'
TYPE_VOLUME = 'volume'
TYPE_OBJECT = 'object'
class ResourceType(StrEnum):
HOST = 'host'
INSTANCE = 'instance'
AMI = 'ami'
SNAPSHOT = 'snapshot'
VOLUME = 'volume'
OBJECT = 'object'
def __init__(self, metadata, type, id):
super().__init__(metadata, type)
+4
View File
@@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from enum import StrEnum
import time
@@ -143,6 +144,9 @@ class Resource:
"""
class ResourceType(StrEnum):
pass
def __init__(self, metadata, type):
self.type = type
self.metadata = metadata