@@ -5006,6 +5006,7 @@ def __init__(self):
50065006 group .add_argument ('--filter-binary' , choices = ['1' , '0' ], metavar = '<1|0>' , default = None , dest = 'filter_binary' ,
50075007 help = 'When set to true binary documents are not replicated. When false binary documents may '
50085008 'be replicated' )
5009+ group .add_argument ('--force' , action = 'store_true' , help = 'Skips any confirmation prompts' )
50095010
50105011 collection_group = self .parser .add_argument_group ("Collection options" )
50115012 collection_group .add_argument ('--collection-explicit-mappings' , choices = ['1' , '0' ], metavar = '<1|0>' ,
@@ -5018,6 +5019,22 @@ def __init__(self):
50185019 help = 'The mapping rules specified as a JSON formatted string. '
50195020 '(Enterprise Edition Only)' )
50205021
5022+ conflict_logging_group = self .parser .add_argument_group ("Conflict logging options" )
5023+ conflict_logging_group .add_argument ('--conflict-logging' , choices = ['1' , '0' ], metavar = '<1|0>' ,
5024+ default = None , help = 'Whether conflict logging should be enabled' )
5025+ conflict_logging_group .add_argument (
5026+ '--conflict-logging-default' , type = str , metavar = '<collection-string>' ,
5027+ help = 'A collection string specifying the default location for conflict logs' )
5028+ conflict_logging_group .add_argument ('--conflict-logging-rule-map' , type = str , metavar = '<mapping>' ,
5029+ action = 'append' , help = 'A mapping from a scope/collection on the source to '
5030+ 'a collection string on the destination' )
5031+ conflict_logging_group .add_argument ('--conflict-logging-rule-default' , type = str , metavar = '<collection>' ,
5032+ action = 'append' , help = 'Use the replication default for the given '
5033+ 'scope/collection' )
5034+ conflict_logging_group .add_argument ('--conflict-logging-rule-disable' , type = str , metavar = '<collection>' ,
5035+ action = 'append' , help = 'Disable conflict logging for specified '
5036+ 'scope/collection' )
5037+
50215038 @rest_initialiser (cluster_init_check = True , version_check = True , enterprise_check = False )
50225039 def execute (self , opts ):
50235040 if not self .enterprise and opts .compression :
@@ -5059,19 +5076,104 @@ def _get(self, opts):
50595076 _exit_if_errors (errors )
50605077 print (json .dumps (settings , indent = 4 , sort_keys = True ))
50615078
5079+ def _parse_conflict_logging_args (self , opts ):
5080+ if opts .conflict_logging is None :
5081+ return None
5082+
5083+ if opts .conflict_logging == "1" and not opts .conflict_logging_default :
5084+ _exit_if_errors (["if conflict-logging is enabled --conflict-logging-default is needed" ])
5085+ if opts .conflict_logging != "1" and opts .conflict_logging_default :
5086+ _exit_if_errors (["if conflict-logging is disabled --conflict-logging-default cannot be passed" ])
5087+
5088+ data = {}
5089+ if opts .conflict_logging == "0" :
5090+ data ["disabled" ] = True
5091+ return data
5092+
5093+ if not opts .force :
5094+ choice = prompt_for_confirmation (
5095+ "Enabling conflict logging requires the source and destination clusters to "
5096+ "be on 8.0 or later, and have cross cluster versioning enabled." )
5097+ if not choice :
5098+ sys .exit (0 )
5099+
5100+ data ["disabled" ] = False
5101+
5102+ default_cs , errors = CollectionStringParser (opts .conflict_logging_default ).parse ()
5103+ _exit_if_errors ([f"error parsing { opts .conflict_logging_default } : { e } " for e in errors ])
5104+
5105+ if default_cs .collection is None :
5106+ _exit_if_errors (["conflict logging default destination must be to a collection" ])
5107+
5108+ data ["bucket" ] = default_cs .bucket
5109+ data ["collection" ] = f"{ default_cs .scope } .{ default_cs .collection } "
5110+
5111+ rules = {}
5112+ if opts .conflict_logging_rule_map :
5113+ for rule in opts .conflict_logging_rule_map :
5114+ # This is safe because bucket, scope and collection names cannot contain an equals
5115+ split = rule .split ('=' , 1 )
5116+ if len (split ) != 2 :
5117+ _exit_if_errors ([f"no '=' in log rule { rule } " ])
5118+
5119+ src , errors = CollectionStringParser (split [0 ]).parse (start_at = "scope" )
5120+ _exit_if_errors ([f"error parsing { split [0 ]} : { e } " for e in errors ])
5121+
5122+ if split [1 ] == "" :
5123+ _exit_if_errors ([f"error parsing { rule } : no destination specified" ])
5124+
5125+ dst , errors = CollectionStringParser (split [1 ]).parse ()
5126+ _exit_if_errors ([f"error parsing { split [1 ]} : { e } " for e in errors ])
5127+
5128+ if dst .levels () != 3 :
5129+ _exit_if_errors (["the destination for a rule must be a collection" ])
5130+
5131+ rules [src .scope_collection_string ()] = {
5132+ "bucket" : dst .bucket ,
5133+ "collection" : dst .scope_collection_string ()
5134+ }
5135+
5136+ if opts .conflict_logging_rule_default :
5137+ for collection in opts .conflict_logging_rule_default :
5138+ src , errors = CollectionStringParser (collection ).parse (start_at = "scope" )
5139+ _exit_if_errors ([f"error parsing { split [0 ]} : { e } " for e in errors ])
5140+
5141+ rules [src .scope_collection_string ()] = {}
5142+
5143+ if opts .conflict_logging_rule_disable :
5144+ for collection in opts .conflict_logging_rule_disable :
5145+ src , errors = CollectionStringParser (collection ).parse (start_at = "scope" )
5146+ _exit_if_errors ([f"error parsing { split [0 ]} : { e } " for e in errors ])
5147+
5148+ rules [src .scope_collection_string ()] = None
5149+
5150+ data ["loggingRules" ] = rules
5151+
5152+ return data
5153+
50625154 def _create (self , opts ):
50635155 if opts .collection_migration == '1' and opts .collection_explicit_mappings == '1' :
50645156 _exit_if_errors (['cannot enable both collection migration and explicit mappings' ])
5157+
50655158 if opts .filter_skip and opts .filter is None :
50665159 _exit_if_errors (["--filter-expression is needed with the --filter-skip-restream option" ])
5160+
5161+ if opts .conflict_logging == '1' and not opts .conflict_logging_default :
5162+ _exit_if_errors (["if conflict-logging is enabled --conflict-logging-default is needed" ])
5163+ if opts .conflict_logging != '1' and opts .conflict_logging_default :
5164+ _exit_if_errors (["if conflict-logging is disabled --conflict-logging-default cannot be passed" ])
5165+
5166+ conflict_logging = self ._parse_conflict_logging_args (opts )
5167+
50675168 _ , errors = self .rest .create_xdcr_replication (opts .cluster_name , opts .to_bucket , opts .from_bucket , opts .chk_int ,
50685169 opts .worker_batch_size , opts .doc_batch_size , opts .fail_interval ,
50695170 opts .rep_thresh , opts .src_nozzles , opts .dst_nozzles ,
50705171 opts .usage_limit , opts .compression , opts .log_level ,
50715172 opts .stats_interval , opts .filter , opts .priority ,
50725173 opts .reset_expiry , opts .filter_del , opts .filter_exp ,
50735174 opts .filter_binary , opts .collection_explicit_mappings ,
5074- opts .collection_migration , opts .collection_mapping_rules )
5175+ opts .collection_migration , opts .collection_mapping_rules ,
5176+ conflict_logging )
50755177 _exit_if_errors (errors )
50765178
50775179 _success ("XDCR replication created" )
@@ -5127,14 +5229,17 @@ def _settings(self, opts):
51275229 _exit_if_errors (["--filter-expression is needed with the --filter-skip-restream option" ])
51285230 if opts .collection_migration == '1' and opts .collection_explicit_mappings == '1' :
51295231 _exit_if_errors (['cannot enable both collection migration and explicit mappings' ])
5232+
5233+ conflict_logging = self ._parse_conflict_logging_args (opts )
5234+
51305235 _ , errors = self .rest .xdcr_replicator_settings (opts .chk_int , opts .worker_batch_size , opts .doc_batch_size ,
51315236 opts .fail_interval , opts .rep_thresh , opts .src_nozzles ,
51325237 opts .dst_nozzles , opts .usage_limit , opts .compression ,
51335238 opts .log_level , opts .stats_interval , opts .replicator_id ,
51345239 opts .filter , opts .filter_skip , opts .priority , opts .reset_expiry ,
51355240 opts .filter_del , opts .filter_exp , opts .filter_binary ,
51365241 opts .collection_explicit_mappings , opts .collection_migration ,
5137- opts .collection_mapping_rules )
5242+ opts .collection_mapping_rules , conflict_logging )
51385243 _exit_if_errors (errors )
51395244
51405245 _success ("XDCR replicator settings updated" )
0 commit comments