88import shutil
99
1010
11+ def _docker_noop ():
12+ 'Docker resources managed by compose'
13+ return {'destroyed' : True , 'message' : 'Remove via docker compose down -v' }
14+
15+ def _not_found (msg ):
16+ 'Resource not found response'
17+ return {'destroyed' : False , 'message' : msg }
18+
19+ def _success (msg ):
20+ 'Successful deletion response'
21+ return {'destroyed' : True , 'message' : msg }
22+
23+
1124def destroy (resource_type , name , provider = 'docker' , ** kw ):
1225 'Destroy a single provisioned resource'
1326 dispatchers = {
14- 'database' : _destroy_database ,
15- 'cache' : _destroy_cache ,
16- 'queue' : _destroy_queue ,
17- 'bucket' : _destroy_bucket ,
18- 'llm' : _destroy_llm ,
19- 'search' : _destroy_search ,
27+ 'database' : _destroy_database , 'cache' : _destroy_cache , 'queue' : _destroy_queue ,
28+ 'bucket' : _destroy_bucket , 'llm' : _destroy_llm , 'search' : _destroy_search ,
2029 'function' : _destroy_function
2130 }
22-
2331 if resource_type not in dispatchers :
2432 return {'destroyed' : False , 'resource' : name , 'provider' : provider ,
2533 'message' : f'Unknown resource type: { resource_type } ' }
26-
2734 result = dispatchers [resource_type ](name , provider , ** kw )
2835 result .setdefault ('resource' , name )
2936 result .setdefault ('provider' , provider )
@@ -32,240 +39,171 @@ def destroy(resource_type, name, provider='docker', **kw):
3239
3340def _destroy_database (name , provider , ** kw ):
3441 'Destroy a database instance'
35- if provider == 'docker' :
36- return {'destroyed' : True , 'message' : 'Remove via docker compose down -v' }
37-
42+ if provider == 'docker' : return _docker_noop ()
3843 elif provider == 'aws' :
3944 from .aws import callaws
4045 try :
41- callaws ('rds' , 'delete-db-instance' ,
42- '--db-instance-identifier' , name ,
43- '--skip-final-snapshot' ,
44- '--delete-automated-backups' )
46+ callaws ('rds' , 'delete-db-instance' , '--db-instance-identifier' , name ,
47+ '--skip-final-snapshot' , '--delete-automated-backups' )
4548 except Exception as e :
46- if 'DBInstanceNotFound' in str (e ):
47- return {'destroyed' : False , 'message' : f'RDS instance { name } not found' }
49+ if 'DBInstanceNotFound' in str (e ): return _not_found (f'RDS instance { name } not found' )
4850 raise
49- return {'destroyed' : True , 'message' : f'RDS instance { name } deletion initiated' }
50-
51+ return _success (f'RDS instance { name } deletion initiated' )
5152 elif provider == 'azure' :
5253 from .azure import callaz
5354 rg = kw .get ('resource_group' )
5455 try :
55- callaz ('postgres' , 'flexible-server' , 'delete' ,
56- '--name' , name ,
57- '--resource-group' , rg ,
58- '--yes' )
56+ callaz ('postgres' , 'flexible-server' , 'delete' , '--name' , name ,
57+ '--resource-group' , rg , '--yes' )
5958 except Exception as e :
60- if 'ResourceNotFound' in str (e ):
61- return {'destroyed' : False , 'message' : f'Azure DB { name } not found' }
59+ if 'ResourceNotFound' in str (e ): return _not_found (f'Azure DB { name } not found' )
6260 raise
63- return {'destroyed' : True , 'message' : f'Azure Postgres { name } deleted' }
64-
65- return {'destroyed' : False , 'message' : f'Unsupported provider: { provider } ' }
61+ return _success (f'Azure Postgres { name } deleted' )
62+ return _not_found (f'Unsupported provider: { provider } ' )
6663
6764
6865def _destroy_cache (name , provider , ** kw ):
6966 'Destroy a cache instance'
70- if provider == 'docker' :
71- return {'destroyed' : True , 'message' : 'Remove via docker compose down -v' }
72-
67+ if provider == 'docker' : return _docker_noop ()
7368 elif provider == 'aws' :
7469 from .aws import callaws
7570 try :
76- callaws ('elasticache' , 'delete-cache-cluster' ,
77- '--cache-cluster-id' , name )
71+ callaws ('elasticache' , 'delete-cache-cluster' , '--cache-cluster-id' , name )
7872 except Exception as e :
79- if 'CacheClusterNotFound' in str (e ):
80- return {'destroyed' : False , 'message' : f'ElastiCache cluster { name } not found' }
73+ if 'CacheClusterNotFound' in str (e ): return _not_found (f'ElastiCache cluster { name } not found' )
8174 raise
82- return {'destroyed' : True , 'message' : f'ElastiCache cluster { name } deletion initiated' }
83-
75+ return _success (f'ElastiCache cluster { name } deletion initiated' )
8476 elif provider == 'azure' :
8577 from .azure import callaz
8678 rg = kw .get ('resource_group' )
8779 try :
88- callaz ('redis' , 'delete' ,
89- '--name' , name ,
90- '--resource-group' , rg ,
91- '--yes' )
80+ callaz ('redis' , 'delete' , '--name' , name , '--resource-group' , rg , '--yes' )
9281 except Exception as e :
93- if 'ResourceNotFound' in str (e ):
94- return {'destroyed' : False , 'message' : f'Azure Redis { name } not found' }
82+ if 'ResourceNotFound' in str (e ): return _not_found (f'Azure Redis { name } not found' )
9583 raise
96- return {'destroyed' : True , 'message' : f'Azure Redis { name } deleted' }
97-
98- return {'destroyed' : False , 'message' : f'Unsupported provider: { provider } ' }
84+ return _success (f'Azure Redis { name } deleted' )
85+ return _not_found (f'Unsupported provider: { provider } ' )
9986
10087
10188def _destroy_queue (name , provider , ** kw ):
10289 'Destroy a message queue'
103- if provider == 'docker' :
104- return {'destroyed' : True , 'message' : 'Remove via docker compose down -v' }
105-
90+ if provider == 'docker' : return _docker_noop ()
10691 elif provider == 'aws' :
10792 from .aws import callaws
10893 try :
109- # Get queue URL first
11094 result = callaws ('sqs' , 'get-queue-url' , '--queue-name' , name )
111- url = result ['QueueUrl' ]
112- # Delete the queue
113- callaws ('sqs' , 'delete-queue' , '--queue-url' , url )
95+ callaws ('sqs' , 'delete-queue' , '--queue-url' , result ['QueueUrl' ])
11496 except Exception as e :
11597 if 'NonExistentQueue' in str (e ) or 'QueueDoesNotExist' in str (e ):
116- return { 'destroyed' : False , 'message' : f'SQS queue { name } not found' }
98+ return _not_found ( f'SQS queue { name } not found' )
11799 raise
118- return {'destroyed' : True , 'message' : f'SQS queue { name } deleted' }
119-
100+ return _success (f'SQS queue { name } deleted' )
120101 elif provider == 'azure' :
121102 from .azure import callaz
122103 rg = kw .get ('resource_group' )
123104 namespace = kw .get ('namespace' , f'{ name } -ns' )
124105 try :
125- callaz ('servicebus' , 'namespace' , 'delete' ,
126- '--name' , namespace ,
127- '--resource-group' , rg ,
128- '--yes' )
106+ callaz ('servicebus' , 'namespace' , 'delete' , '--name' , namespace ,
107+ '--resource-group' , rg , '--yes' )
129108 except Exception as e :
130- if 'ResourceNotFound' in str (e ):
131- return {'destroyed' : False , 'message' : f'Azure ServiceBus namespace { namespace } not found' }
109+ if 'ResourceNotFound' in str (e ): return _not_found (f'Azure ServiceBus namespace { namespace } not found' )
132110 raise
133- return {'destroyed' : True , 'message' : f'Azure ServiceBus namespace { namespace } deleted' }
134-
111+ return _success (f'Azure ServiceBus namespace { namespace } deleted' )
135112 elif provider == 'gcp' :
136113 try :
137- # Delete subscription first
138114 sub_name = f'{ name } -sub'
139115 subprocess .run (['gcloud' , 'pubsub' , 'subscriptions' , 'delete' , sub_name , '--quiet' ],
140116 capture_output = True , text = True , check = True )
141- # Delete topic
142117 subprocess .run (['gcloud' , 'pubsub' , 'topics' , 'delete' , name , '--quiet' ],
143118 capture_output = True , text = True , check = True )
144119 except subprocess .CalledProcessError as e :
145120 if 'NOT_FOUND' in e .stderr or 'does not exist' in e .stderr .lower ():
146- return { 'destroyed' : False , 'message' : f'GCP Pub/Sub topic { name } not found' }
121+ return _not_found ( f'GCP Pub/Sub topic { name } not found' )
147122 raise
148- return {'destroyed' : True , 'message' : f'GCP Pub/Sub topic { name } deleted' }
149-
150- return {'destroyed' : False , 'message' : f'Unsupported provider: { provider } ' }
123+ return _success (f'GCP Pub/Sub topic { name } deleted' )
124+ return _not_found (f'Unsupported provider: { provider } ' )
151125
152126
153127def _destroy_bucket (name , provider , ** kw ):
154128 'Destroy object storage bucket'
155- if provider == 'docker' :
156- return {'destroyed' : True , 'message' : 'Remove via docker compose down -v' }
157-
129+ if provider == 'docker' : return _docker_noop ()
158130 elif provider == 'aws' :
159131 from .aws import callaws
160132 try :
161- # Empty bucket first
162133 callaws ('s3' , 'rm' , f's3://{ name } ' , '--recursive' )
163- # Delete bucket
164134 callaws ('s3api' , 'delete-bucket' , '--bucket' , name )
165135 except Exception as e :
166- if 'NoSuchBucket' in str (e ):
167- return {'destroyed' : False , 'message' : f'S3 bucket { name } not found' }
136+ if 'NoSuchBucket' in str (e ): return _not_found (f'S3 bucket { name } not found' )
168137 raise
169- return {'destroyed' : True , 'message' : f'S3 bucket { name } deleted' }
170-
138+ return _success (f'S3 bucket { name } deleted' )
171139 elif provider == 'azure' :
172140 from .azure import callaz
173141 rg = kw .get ('resource_group' )
174142 account_name = kw .get ('account_name' , name .replace ('-' , '' ).replace ('_' , '' )[:24 ])
175143 try :
176- # Delete container
177- callaz ('storage' , 'container' , 'delete' ,
178- '--name' , name ,
179- '--account-name' , account_name ,
180- '--yes' )
181- # Delete storage account
182- callaz ('storage' , 'account' , 'delete' ,
183- '--name' , account_name ,
184- '--resource-group' , rg ,
185- '--yes' )
144+ callaz ('storage' , 'container' , 'delete' , '--name' , name ,
145+ '--account-name' , account_name , '--yes' )
146+ callaz ('storage' , 'account' , 'delete' , '--name' , account_name ,
147+ '--resource-group' , rg , '--yes' )
186148 except Exception as e :
187149 if 'ResourceNotFound' in str (e ) or 'NotFound' in str (e ):
188- return { 'destroyed' : False , 'message' : f'Azure storage { name } not found' }
150+ return _not_found ( f'Azure storage { name } not found' )
189151 raise
190- return {'destroyed' : True , 'message' : f'Azure storage account { account_name } deleted' }
191-
152+ return _success (f'Azure storage account { account_name } deleted' )
192153 elif provider == 'gcp' :
193154 try :
194155 subprocess .run (['gcloud' , 'storage' , 'rm' , '-r' , f'gs://{ name } ' , '--quiet' ],
195156 capture_output = True , text = True , check = True )
196157 except subprocess .CalledProcessError as e :
197158 if 'NOT_FOUND' in e .stderr or 'does not exist' in e .stderr .lower ():
198- return { 'destroyed' : False , 'message' : f'GCS bucket { name } not found' }
159+ return _not_found ( f'GCS bucket { name } not found' )
199160 raise
200- return {'destroyed' : True , 'message' : f'GCS bucket { name } deleted' }
201-
202- return {'destroyed' : False , 'message' : f'Unsupported provider: { provider } ' }
161+ return _success (f'GCS bucket { name } deleted' )
162+ return _not_found (f'Unsupported provider: { provider } ' )
203163
204164
205165def _destroy_llm (name , provider , ** kw ):
206166 'Destroy LLM endpoint'
207- if provider == 'docker' :
208- return {'destroyed' : True , 'message' : 'Remove via docker compose down -v' }
209-
210- elif provider == 'openai' :
211- return {'destroyed' : True , 'message' : 'No teardown needed for OpenAI' }
212-
167+ if provider == 'docker' : return _docker_noop ()
168+ elif provider == 'openai' : return _success ('No teardown needed for OpenAI' )
213169 elif provider == 'azure' :
214170 from .azure import callaz
215171 rg = kw .get ('resource_group' )
216172 deployment_name = kw .get ('deployment' , f'{ name } -deployment' )
217173 try :
218- # Delete deployment
219174 callaz ('cognitiveservices' , 'account' , 'deployment' , 'delete' ,
220- '--name' , name ,
221- '--resource-group' , rg ,
222- '--deployment-name' , deployment_name )
223- # Delete account
175+ '--name' , name , '--resource-group' , rg , '--deployment-name' , deployment_name )
224176 callaz ('cognitiveservices' , 'account' , 'delete' ,
225- '--name' , name ,
226- '--resource-group' , rg )
177+ '--name' , name , '--resource-group' , rg )
227178 except Exception as e :
228- if 'ResourceNotFound' in str (e ):
229- return {'destroyed' : False , 'message' : f'Azure OpenAI { name } not found' }
179+ if 'ResourceNotFound' in str (e ): return _not_found (f'Azure OpenAI { name } not found' )
230180 raise
231- return {'destroyed' : True , 'message' : f'Azure OpenAI account { name } deleted' }
232-
233- elif provider == 'aws' :
234- return {'destroyed' : True , 'message' : 'No teardown needed for Bedrock' }
235-
236- return {'destroyed' : False , 'message' : f'Unsupported provider: { provider } ' }
181+ return _success (f'Azure OpenAI account { name } deleted' )
182+ elif provider == 'aws' : return _success ('No teardown needed for Bedrock' )
183+ return _not_found (f'Unsupported provider: { provider } ' )
237184
238185
239186def _destroy_search (name , provider , ** kw ):
240187 'Destroy search engine'
241- if provider == 'docker' :
242- return {'destroyed' : True , 'message' : 'Remove via docker compose down -v' }
243-
188+ if provider == 'docker' : return _docker_noop ()
244189 elif provider == 'aws' :
245190 from .aws import callaws
246191 try :
247192 callaws ('opensearch' , 'delete-domain' , '--domain-name' , name )
248193 except Exception as e :
249- if 'ResourceNotFoundException' in str (e ):
250- return {'destroyed' : False , 'message' : f'OpenSearch domain { name } not found' }
194+ if 'ResourceNotFoundException' in str (e ): return _not_found (f'OpenSearch domain { name } not found' )
251195 raise
252- return {'destroyed' : True , 'message' : f'OpenSearch domain { name } deletion initiated' }
253-
196+ return _success (f'OpenSearch domain { name } deletion initiated' )
254197 elif provider == 'azure' :
255198 from .azure import callaz
256199 rg = kw .get ('resource_group' )
257200 try :
258- callaz ('search' , 'service' , 'delete' ,
259- '--name' , name ,
260- '--resource-group' , rg ,
261- '--yes' )
201+ callaz ('search' , 'service' , 'delete' , '--name' , name , '--resource-group' , rg , '--yes' )
262202 except Exception as e :
263- if 'ResourceNotFound' in str (e ):
264- return {'destroyed' : False , 'message' : f'Azure Search { name } not found' }
203+ if 'ResourceNotFound' in str (e ): return _not_found (f'Azure Search { name } not found' )
265204 raise
266- return {'destroyed' : True , 'message' : f'Azure Search { name } deleted' }
267-
268- return {'destroyed' : False , 'message' : f'Unsupported provider: { provider } ' }
205+ return _success (f'Azure Search { name } deleted' )
206+ return _not_found (f'Unsupported provider: { provider } ' )
269207
270208
271209def _destroy_function (name , provider , ** kw ):
@@ -275,38 +213,29 @@ def _destroy_function(name, provider, **kw):
275213 try :
276214 callaws ('lambda' , 'delete-function' , '--function-name' , name )
277215 except Exception as e :
278- if 'ResourceNotFoundException' in str (e ):
279- return {'destroyed' : False , 'message' : f'Lambda function { name } not found' }
216+ if 'ResourceNotFoundException' in str (e ): return _not_found (f'Lambda function { name } not found' )
280217 raise
281- return {'destroyed' : True , 'message' : f'Lambda function { name } deleted' }
282-
218+ return _success (f'Lambda function { name } deleted' )
283219 elif provider == 'azure' :
284220 from .azure import callaz
285221 rg = kw .get ('resource_group' )
286222 try :
287- callaz ('functionapp' , 'delete' ,
288- '--name' , name ,
289- '--resource-group' , rg ,
290- '--yes' )
223+ callaz ('functionapp' , 'delete' , '--name' , name , '--resource-group' , rg , '--yes' )
291224 except Exception as e :
292- if 'ResourceNotFound' in str (e ):
293- return {'destroyed' : False , 'message' : f'Azure Function { name } not found' }
225+ if 'ResourceNotFound' in str (e ): return _not_found (f'Azure Function { name } not found' )
294226 raise
295- return {'destroyed' : True , 'message' : f'Azure Function { name } deleted' }
296-
227+ return _success (f'Azure Function { name } deleted' )
297228 elif provider == 'gcp' :
298229 region = kw .get ('region' , 'us-central1' )
299230 try :
300- subprocess .run (['gcloud' , 'functions' , 'delete' , name ,
301- '--quiet' , '--region' , region ],
231+ subprocess .run (['gcloud' , 'functions' , 'delete' , name , '--quiet' , '--region' , region ],
302232 capture_output = True , text = True , check = True )
303233 except subprocess .CalledProcessError as e :
304234 if 'NOT_FOUND' in e .stderr or 'does not exist' in e .stderr .lower ():
305- return { 'destroyed' : False , 'message' : f'GCP function { name } not found' }
235+ return _not_found ( f'GCP function { name } not found' )
306236 raise
307- return {'destroyed' : True , 'message' : f'GCP function { name } deleted' }
308-
309- return {'destroyed' : False , 'message' : f'Unsupported provider: { provider } ' }
237+ return _success (f'GCP function { name } deleted' )
238+ return _not_found (f'Unsupported provider: { provider } ' )
310239
311240
312241def _infer_resource_type (env_dict ):
0 commit comments