Skip to content

Commit 1a2a239

Browse files
franklwyLiu WenyuEriczhang3
authored
Feature/eip (#139)
* Add files via upload add huaweicloud Kafka custodian * Changes set-config Delete json-diff * delete import * rename set_config * Feature/dns (#9) add dns actions, filters, UTs * Feature/dns (#10) * add readme_dns * add readme_dns * add readme_dns * Update readme_dns.md * Update readme_dns.md * add dns * update readme_dns * update kafka * update client * update dns * update dns * update dns add dns_test * update dns_test update mock * add mock * update dns * Delete tools/c7n_huaweicloud/c7n_huaweicloud/resources/dns_files directory * update dns lint * lint modify * lint modify * modify * modify * update test --------- Co-authored-by: Liu Wenyu <[email protected]> * Create readme_dns.md * eip 代码提交 * eip 门禁问题修改 * eip delete场景逻辑修改 * eip delete场景逻辑修改 * eip 门禁修改 * eip 门禁修改 * eip 门禁修改 * eip delete逻辑调整 * eip delete逻辑调整 * eip for循环逻辑调整 * eip 门禁问题修改 * Delete readme_dns.md * Delete tools/c7n_huaweicloud/c7n_huaweicloud/reademe_eip.md * 删除reademe_dns.md文件 * poetry.lock 文件更新 * poetry.lock 文件更新 * 代码超长 更新 * 添加test_bms.py文件 * client.py 中删除bms部分 --------- Co-authored-by: Liu Wenyu <[email protected]> Co-authored-by: Ericzhang3 <[email protected]>
1 parent a91e154 commit 1a2a239

18 files changed

+1600
-76
lines changed

tools/c7n_huaweicloud/c7n_huaweicloud/client.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@
5555
ListListenersRequest,
5656
)
5757
from huaweicloudsdkeip.v3.region.eip_region import EipRegion
58-
from huaweicloudsdkeip.v3 import EipClient
58+
from huaweicloudsdkeip.v3 import EipClient, ListPublicipsRequest
59+
from huaweicloudsdkeip.v2 import EipClient as EipClientV2
60+
from huaweicloudsdkeip.v2.region.eip_region import EipRegion as EipRegionV2
5961
from huaweicloudsdkgeip.v3.region.geip_region import GeipRegion
6062
from huaweicloudsdkgeip.v3 import GeipClient
6163
from huaweicloudsdkims.v2.region.ims_region import ImsRegion
@@ -299,6 +301,13 @@ def client(self, service):
299301
.with_region(EipRegion.value_of(self.region))
300302
.build()
301303
)
304+
elif service == "eip_v2":
305+
client = (
306+
EipClientV2.new_builder()
307+
.with_credentials(credentials)
308+
.with_region(EipRegionV2.value_of(self.region))
309+
.build()
310+
)
302311
elif service == "geip":
303312
client = (
304313
GeipClient.new_builder()
@@ -525,6 +534,8 @@ def request(self, service):
525534
request = ListLoadBalancersRequest()
526535
elif service == "elb_listener":
527536
request = ListListenersRequest()
537+
elif service == "eip":
538+
request = ListPublicipsRequest()
528539
elif service == "ims":
529540
request = ListImagesRequest()
530541
elif service == "smn":
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
# Copyright The Cloud Custodian Authors.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
import logging
5+
6+
from huaweicloudsdkcore.exceptions import exceptions
7+
from huaweicloudsdkeip.v2 import DeletePublicipRequest
8+
from huaweicloudsdkeip.v3 import DisassociatePublicipsRequest
9+
10+
from c7n.utils import type_schema, local_session
11+
from c7n.filters import Filter
12+
from c7n_huaweicloud.actions.base import HuaweiCloudBaseAction
13+
from c7n_huaweicloud.provider import resources
14+
from c7n_huaweicloud.query import QueryResourceManager, TypeInfo
15+
16+
log = logging.getLogger("custodian.huaweicloud.resources.eip")
17+
18+
19+
@resources.register("eip")
20+
class EIP(QueryResourceManager):
21+
"""HuaweiCloud Elastic IP Resource
22+
23+
:example:
24+
25+
.. code-block:: yaml
26+
27+
policies:
28+
- name: eip-unattached
29+
resource: huaweicloud.eip
30+
filters:
31+
- type: value
32+
key: status
33+
value: DOWN
34+
"""
35+
36+
class resource_type(TypeInfo):
37+
service = "eip"
38+
enum_spec = ("list_publicips", "publicips", "marker")
39+
id = "id"
40+
tag_resource_type = "eip"
41+
42+
43+
@EIP.filter_registry.register("associate-instance-type")
44+
class AssociateInstanceTypeFilter(Filter):
45+
"""EIP Associated Instance Type Filter
46+
47+
Filter EIPs based on associated instance type (e.g., PORT, NATGW, ELB, ELBV1, VPN, etc.)
48+
49+
:example:
50+
51+
.. code-block:: yaml
52+
53+
policies:
54+
- name: eip-associated-with-elb
55+
resource: huaweicloud.eip
56+
filters:
57+
- type: associate-instance-type
58+
instance_type: ELB
59+
"""
60+
schema = type_schema(
61+
"associate-instance-type",
62+
instance_type={"type": "string", "enum": ["PORT", "NATGW", "ELB", "ELBV1", "VPN", "NONE"]},
63+
required=["instance_type"]
64+
)
65+
66+
def process(self, resources, event=None):
67+
instance_type = self.data.get("instance_type")
68+
results = []
69+
70+
for resource in resources:
71+
# Check if associate_instance_type is empty (not associated with any instance)
72+
resource_instance_type = resource.get("associate_instance_type", "")
73+
74+
if not resource_instance_type:
75+
# Not associated with any instance
76+
if instance_type == "NONE":
77+
results.append(resource)
78+
continue
79+
80+
# Match based on associate_instance_type returned by API
81+
if resource_instance_type == instance_type:
82+
results.append(resource)
83+
84+
return results
85+
86+
87+
@EIP.action_registry.register("delete")
88+
class EIPDelete(HuaweiCloudBaseAction):
89+
"""Delete Elastic IP
90+
91+
Automatically disassociates the EIP before deletion if it's bound to an instance
92+
93+
Note: If the EIP is associated with a NATGW instance, please use nat-snat-rule or nat-dnat-rule
94+
delete actions instead
95+
96+
:example:
97+
98+
.. code-block:: yaml
99+
100+
policies:
101+
- name: delete-unassociated-eips
102+
resource: huaweicloud.eip
103+
filters:
104+
- type: value
105+
key: status
106+
value: DOWN
107+
actions:
108+
- delete
109+
"""
110+
schema = type_schema("delete")
111+
112+
def process(self, resources):
113+
session = local_session(self.manager.session_factory)
114+
# Use eip_v3 client for disassociation
115+
client_v3 = self.manager.get_client()
116+
# Use eip_v2 client for deletion
117+
client_v2 = session.client('eip_v2')
118+
processed_resources = []
119+
120+
for resource in resources:
121+
try:
122+
# Check if EIP is associated with NATGW instance
123+
if resource.get("associate_instance_type") == "NATGW":
124+
self.log.error(
125+
f"Cannot delete EIP {resource['id']} associated with NATGW, "
126+
f"please use nat-snat-rule or nat-dnat-rule delete action instead."
127+
)
128+
self.failed_resources.append(resource)
129+
continue
130+
131+
# If EIP status is ACTIVE (bound), disassociate it first
132+
if resource.get("status") == "ACTIVE":
133+
try:
134+
request = DisassociatePublicipsRequest()
135+
request.publicip_id = resource["id"]
136+
client_v3.disassociate_publicips(request)
137+
self.log.info(f"Successfully disassociated EIP {resource['id']}")
138+
except exceptions.ClientRequestException as e:
139+
self.log.error(
140+
f"Failed to disassociate EIP {resource['id']}, "
141+
f"Request ID: {e.request_id},"
142+
f" Error Code: {e.error_code}, Error Message: {e.error_msg}"
143+
)
144+
self.failed_resources.append(resource)
145+
continue
146+
147+
# Perform deletion
148+
request = DeletePublicipRequest(publicip_id=resource["id"])
149+
client_v2.delete_publicip(request)
150+
self.log.info(f"Successfully deleted EIP {resource['id']}")
151+
processed_resources.append(resource)
152+
except exceptions.ClientRequestException as e:
153+
self.log.error(
154+
f"Failed to delete EIP {resource['id']}, "
155+
f"Request ID: {e.request_id}, Error Code: {e.error_code}"
156+
f", Error Message: {e.error_msg}"
157+
)
158+
self.failed_resources.append(resource)
159+
160+
# Add successfully processed resources to the result
161+
self.result.get("succeeded_resources").extend(processed_resources)
162+
return self.result
163+
164+
def perform_action(self, resource):
165+
# No additional operation needed as we have
166+
# already processed each resource in the process method
167+
pass
168+
169+
170+
@EIP.action_registry.register("disassociate")
171+
class EIPDisassociate(HuaweiCloudBaseAction):
172+
"""Disassociate Elastic IP
173+
174+
Disassociates an EIP from the instance it is bound to
175+
176+
Note: If the EIP is associated with a NATGW instance,
177+
please use nat-snat-rule or nat-dnat-rule
178+
delete actions instead
179+
180+
:example:
181+
182+
.. code-block:: yaml
183+
184+
policies:
185+
- name: disassociate-eips-from-instances
186+
resource: huaweicloud.eip
187+
filters:
188+
- type: value
189+
key: status
190+
value: ACTIVE
191+
actions:
192+
- disassociate
193+
"""
194+
schema = type_schema("disassociate")
195+
196+
def process(self, resources):
197+
client = self.manager.get_client()
198+
# Filter EIPs with ACTIVE status (bound to instances)
199+
active_resources = [r for r in resources if r.get("status") == "ACTIVE"]
200+
processed_resources = []
201+
202+
for resource in active_resources:
203+
try:
204+
# Check if EIP is associated with NATGW instance
205+
if resource.get("associate_instance_type") == "NATGW":
206+
self.log.error(
207+
f"Cannot disassociate EIP {resource['id']} associated with NATGW, "
208+
f"please use nat-snat-rule or nat-dnat-rule delete action instead."
209+
)
210+
self.failed_resources.append(resource)
211+
continue
212+
213+
request = DisassociatePublicipsRequest()
214+
request.publicip_id = resource["id"]
215+
client.disassociate_publicips(request)
216+
self.log.info(f"Successfully disassociated EIP {resource['id']}")
217+
processed_resources.append(resource)
218+
except exceptions.ClientRequestException as e:
219+
self.log.error(
220+
f"Failed to disassociate EIP {resource['id']}, "
221+
f"Request ID: {e.request_id}, Error Code: {e.error_code},"
222+
f" Error Message: {e.error_msg}"
223+
)
224+
self.failed_resources.append(resource)
225+
226+
# Add successfully processed resources to the result
227+
self.result.get("succeeded_resources").extend(processed_resources)
228+
return self.result
229+
230+
def perform_action(self, resource):
231+
# No additional operation needed as we have already
232+
# processed each resource in the process method
233+
pass

tools/c7n_huaweicloud/c7n_huaweicloud/resources/resource_map.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"huaweicloud.ces-alarm": "c7n_huaweicloud.resources.ces.Alarm",
1212
"huaweicloud.kms": "c7n_huaweicloud.resources.kms.Kms",
1313
"huaweicloud.ecs": "c7n_huaweicloud.resources.ecs.Ecs",
14+
"huaweicloud.bms": "c7n_huaweicloud.resources.bms.Bms",
1415
"huaweicloud.iam-user": "c7n_huaweicloud.resources.iam.User",
1516
"huaweicloud.iam-policy": "c7n_huaweicloud.resources.iam.Policy",
1617
"huaweicloud.vpc": "c7n_huaweicloud.resources.vpc.Vpc",
@@ -44,9 +45,9 @@
4445
"huaweicloud.ram-shared-principals": "c7n_huaweicloud.resources.ram.RAMSharedPrincipals",
4546
"huaweicloud.antiddos-eip": "c7n_huaweicloud.resources.antiddos.Eip",
4647
"huaweicloud.kafka": "c7n_huaweicloud.resources.kafka.Kafka",
48+
"huaweicloud.eip": "c7n_huaweicloud.resources.eip.EIP",
4749
"huaweicloud.certificate": "c7n_huaweicloud.resources.scm.Certificate",
4850
"huaweicloud.dc": "c7n_huaweicloud.resources.dc.DC",
4951
"huaweicloud.cc-cloud-connection": "c7n_huaweicloud.resources.cc.CloudConnection",
50-
"huaweicloud.bms": "c7n_huaweicloud.resources.bms.Bms",
5152
"huaweicloud.rds": "c7n_huaweicloud.resources.rds.RDS",
5253
}

0 commit comments

Comments
 (0)