2
2
import os
3
3
import re
4
4
import threading
5
+ from copy import deepcopy
5
6
from datetime import datetime , timezone
6
7
from random import randint
7
8
from typing import Dict , Optional
12
13
from localstack .aws .api .opensearch import (
13
14
ARN ,
14
15
AccessPoliciesStatus ,
15
- AdvancedOptions ,
16
16
AdvancedOptionsStatus ,
17
17
AdvancedSecurityOptions ,
18
- AdvancedSecurityOptionsInput ,
19
18
AdvancedSecurityOptionsStatus ,
20
- AIMLOptionsInput ,
21
19
AutoTuneDesiredState ,
22
20
AutoTuneOptions ,
23
- AutoTuneOptionsInput ,
24
21
AutoTuneOptionsOutput ,
25
22
AutoTuneOptionsStatus ,
26
23
AutoTuneState ,
30
27
CognitoOptions ,
31
28
CognitoOptionsStatus ,
32
29
ColdStorageOptions ,
30
+ CreateDomainRequest ,
33
31
CreateDomainResponse ,
34
32
DeleteDomainResponse ,
35
33
DeploymentStatus ,
50
48
EncryptionAtRestOptionsStatus ,
51
49
EngineType ,
52
50
GetCompatibleVersionsResponse ,
53
- IdentityCenterOptionsInput ,
54
- IPAddressType ,
55
51
ListDomainNamesResponse ,
56
52
ListTagsResponse ,
57
53
ListVersionsResponse ,
58
- LogPublishingOptions ,
59
54
LogPublishingOptionsStatus ,
60
55
MaxResults ,
61
56
NextToken ,
62
57
NodeToNodeEncryptionOptions ,
63
58
NodeToNodeEncryptionOptionsStatus ,
64
- OffPeakWindowOptions ,
65
59
OpensearchApi ,
66
60
OpenSearchPartitionInstanceType ,
67
61
OptionState ,
68
62
OptionStatus ,
69
- PolicyDocument ,
70
63
ResourceAlreadyExistsException ,
71
64
ResourceNotFoundException ,
72
65
RollbackOnDisable ,
73
66
ServiceSoftwareOptions ,
74
67
SnapshotOptions ,
75
68
SnapshotOptionsStatus ,
76
- SoftwareUpdateOptions ,
77
69
StringList ,
78
70
TagList ,
79
71
TLSSecurityPolicy ,
80
72
UpdateDomainConfigRequest ,
81
73
UpdateDomainConfigResponse ,
82
74
ValidationException ,
83
75
VersionStatus ,
84
- VersionString ,
85
76
VolumeType ,
86
77
VPCDerivedInfoStatus ,
87
- VPCOptions ,
88
78
)
89
79
from localstack .constants import OPENSEARCH_DEFAULT_VERSION
90
80
from localstack .services .opensearch import versions
@@ -310,14 +300,20 @@ def get_domain_config_status() -> OptionStatus:
310
300
)
311
301
312
302
313
- def get_domain_status (domain_key : DomainKey , deleted = False ) -> DomainStatus :
303
+ def get_domain_status (
304
+ domain_key : DomainKey , deleted = False , request : CreateDomainRequest | None = None
305
+ ) -> DomainStatus :
314
306
parsed_arn = parse_arn (domain_key .arn )
315
307
store = OpensearchProvider .get_store (parsed_arn ["account" ], parsed_arn ["region" ])
316
308
stored_status : DomainStatus = (
317
309
store .opensearch_domains .get (domain_key .domain_name ) or DomainStatus ()
318
310
)
319
311
cluster_cfg = stored_status .get ("ClusterConfig" ) or {}
320
312
default_cfg = DEFAULT_OPENSEARCH_CLUSTER_CONFIG
313
+ if request :
314
+ stored_status = deepcopy (stored_status )
315
+ stored_status .update (request )
316
+ default_cfg .update (request .get ("ClusterConfig" , {}))
321
317
322
318
domain_processing_status = stored_status .get ("DomainProcessingStatus" , None )
323
319
processing = stored_status .get ("Processing" , True )
@@ -353,7 +349,8 @@ def get_domain_status(domain_key: DomainKey, deleted=False) -> DomainStatus:
353
349
),
354
350
EngineVersion = stored_status .get ("EngineVersion" ) or OPENSEARCH_DEFAULT_VERSION ,
355
351
Endpoint = stored_status .get ("Endpoint" , None ),
356
- EBSOptions = EBSOptions (EBSEnabled = True , VolumeType = VolumeType .gp2 , VolumeSize = 10 , Iops = 0 ),
352
+ EBSOptions = stored_status .get ("EBSOptions" )
353
+ or EBSOptions (EBSEnabled = True , VolumeType = VolumeType .gp2 , VolumeSize = 10 , Iops = 0 ),
357
354
CognitoOptions = CognitoOptions (Enabled = False ),
358
355
UpgradeProcessing = False ,
359
356
AccessPolicies = stored_status .get ("AccessPolicies" , "" ),
@@ -363,6 +360,7 @@ def get_domain_status(domain_key: DomainKey, deleted=False) -> DomainStatus:
363
360
AdvancedOptions = {
364
361
"override_main_response_version" : "false" ,
365
362
"rest.action.multi.allow_explicit_index" : "true" ,
363
+ ** stored_status .get ("AdvancedOptions" , {}),
366
364
},
367
365
ServiceSoftwareOptions = ServiceSoftwareOptions (
368
366
CurrentVersion = "" ,
@@ -486,41 +484,19 @@ def _stop_clusters(self):
486
484
for domain_name in store .opensearch_domains .keys ():
487
485
cluster_manager ().remove (DomainKey (domain_name , region , account_id ).arn )
488
486
487
+ @handler ("CreateDomain" , expand = False )
489
488
def create_domain (
490
- self ,
491
- context : RequestContext ,
492
- domain_name : DomainName ,
493
- engine_version : VersionString = None ,
494
- cluster_config : ClusterConfig = None ,
495
- ebs_options : EBSOptions = None ,
496
- access_policies : PolicyDocument = None ,
497
- ip_address_type : IPAddressType = None ,
498
- snapshot_options : SnapshotOptions = None ,
499
- vpc_options : VPCOptions = None ,
500
- cognito_options : CognitoOptions = None ,
501
- encryption_at_rest_options : EncryptionAtRestOptions = None ,
502
- node_to_node_encryption_options : NodeToNodeEncryptionOptions = None ,
503
- advanced_options : AdvancedOptions = None ,
504
- log_publishing_options : LogPublishingOptions = None ,
505
- domain_endpoint_options : DomainEndpointOptions = None ,
506
- advanced_security_options : AdvancedSecurityOptionsInput = None ,
507
- identity_center_options : IdentityCenterOptionsInput = None ,
508
- tag_list : TagList = None ,
509
- auto_tune_options : AutoTuneOptionsInput = None ,
510
- off_peak_window_options : OffPeakWindowOptions = None ,
511
- software_update_options : SoftwareUpdateOptions = None ,
512
- aiml_options : AIMLOptionsInput = None ,
513
- ** kwargs ,
489
+ self , context : RequestContext , request : CreateDomainRequest
514
490
) -> CreateDomainResponse :
515
491
store = self .get_store (context .account_id , context .region )
516
492
517
- if not is_valid_domain_name (domain_name ):
493
+ if not ( domain_name := request . get ( "DomainName" )) or not is_valid_domain_name (domain_name ):
518
494
# TODO: this should use the server-side validation framework at some point.
519
495
raise ValidationException (
520
496
"Member must satisfy regular expression pattern: [a-z][a-z0-9\\ -]+"
521
497
)
522
498
523
- if domain_endpoint_options :
499
+ if domain_endpoint_options := request . get ( "DomainEndpointOptions" , {}) :
524
500
validate_endpoint_options (domain_endpoint_options )
525
501
526
502
with _domain_mutex :
@@ -533,21 +509,23 @@ def create_domain(
533
509
region = context .region ,
534
510
account = context .account_id ,
535
511
)
536
- security_options = SecurityOptions .from_input (advanced_security_options )
512
+ security_options = SecurityOptions .from_input (request . get ( "AdvancedSecurityOptions" ) )
537
513
538
514
# "create" domain data
539
- store .opensearch_domains [domain_name ] = get_domain_status (domain_key )
515
+ store .opensearch_domains [domain_name ] = get_domain_status (domain_key , request = request )
540
516
if domain_endpoint_options :
541
517
store .opensearch_domains [domain_name ]["DomainEndpointOptions" ] = (
542
518
DEFAULT_OPENSEARCH_DOMAIN_ENDPOINT_OPTIONS | domain_endpoint_options
543
519
)
544
520
545
521
# lazy-init the cluster (sets the Endpoint and Processing flag of the domain status)
546
522
# TODO handle additional parameters (cluster config,...)
547
- create_cluster (domain_key , engine_version , domain_endpoint_options , security_options )
523
+ create_cluster (
524
+ domain_key , request .get ("EngineVersion" ), domain_endpoint_options , security_options
525
+ )
548
526
549
527
# set the tags
550
- self .add_tags (context , domain_key .arn , tag_list )
528
+ self .add_tags (context , domain_key .arn , request . get ( "TagList" ) )
551
529
552
530
# get the (updated) status
553
531
status = get_domain_status (domain_key )
0 commit comments