1import click
2from opnsense_cli.formatters.cli_output import CliOutputFormatter
3from opnsense_cli.callbacks.click import \
4    formatter_from_formatter_name, available_formats, int_as_string, tuple_to_csv, \
5    resolve_linked_names_to_uuids
6from opnsense_cli.types.click_param_type.int_or_empty import INT_OR_EMPTY
7from opnsense_cli.commands.plugin.haproxy import haproxy
8from opnsense_cli.api.client import ApiClient
9from opnsense_cli.api.plugin.haproxy import Settings, Service
10from opnsense_cli.facades.commands.plugin.haproxy.action import HaproxyActionFacade
11
12pass_api_client = click.make_pass_decorator(ApiClient)
13pass_haproxy_action_svc = click.make_pass_decorator(HaproxyActionFacade)
14
15
16@haproxy.group()
17@pass_api_client
18@click.pass_context
19def action(ctx, api_client: ApiClient, **kwargs):
20    """
21    Perform a set of actions if one or more conditions match.
22    """
23    settings_api = Settings(api_client)
24    service_api = Service(api_client)
25    ctx.obj = HaproxyActionFacade(settings_api, service_api)
26
27
28@action.command()
29@click.option(
30    '--output', '-o',
31    help='Specifies the Output format.',
32    default="table",
33    type=click.Choice(available_formats()),
34    callback=formatter_from_formatter_name,
35    show_default=True,
36)
37@click.option(
38    '--cols', '-c',
39    help='Which columns should be printed? Pass empty string (-c '') to show all columns',
40    default=(
41        "uuid,name,description,testType,Acls,operator,type"
42    ),
43    show_default=True,
44)
45@pass_haproxy_action_svc
46def list(haproxy_action_svc: HaproxyActionFacade, **kwargs):
47    """
48    Show all action
49    """
50    result = haproxy_action_svc.list_actions()
51
52    CliOutputFormatter(result, kwargs['output'], kwargs['cols'].split(",")).echo()
53
54
55@action.command()
56@click.argument('uuid')
57@click.option(
58    '--output', '-o',
59    help='Specifies the Output format.',
60    default="table",
61    type=click.Choice(available_formats()),
62    callback=formatter_from_formatter_name,
63    show_default=True,
64)
65@click.option(
66    '--cols', '-c',
67    help='Which columns should be printed? Pass empty string (-c '') to show all columns',
68    default=(
69        "name,description,testType,linkedAcls,Acls,operator,type,use_backend,Backend,use_server,Server,"
70        "http_request_auth,http_request_redirect,http_request_lua,http_request_use_service,"
71        "http_request_add_header_name,"
72        "http_request_add_header_content,http_request_set_header_name,http_request_set_header_content,"
73        "http_request_del_header_name,http_request_replace_header_name,http_request_replace_header_regex,"
74        "http_request_replace_value_name,http_request_replace_value_regex,http_request_set_path,"
75        "http_request_set_var_scope,http_request_set_var_name,http_request_set_var_expr,"
76        "http_response_lua,http_response_add_header_name,http_response_add_header_content,"
77        "http_response_set_header_name,http_response_set_header_content,http_response_del_header_name,"
78        "http_response_replace_header_name,http_response_replace_header_regex,http_response_replace_value_name,"
79        "http_response_replace_value_regex,http_response_set_status_code,http_response_set_status_reason,"
80        "http_response_set_var_scope,http_response_set_var_name,http_response_set_var_expr,tcp_request_content_lua,"
81        "tcp_request_content_use_service,tcp_request_inspect_delay,tcp_response_content_lua,tcp_response_inspect_delay,"
82        "custom,useBackend,Backends,useServer,Servers,actionName,actionFind,actionValue,map_use_backend_file,Mapfile,"
83        "map_use_backend_default,BackendDefault"
84    ),
85    show_default=True,
86)
87@pass_haproxy_action_svc
88def show(haproxy_action_svc: HaproxyActionFacade, **kwargs):
89    """
90    Show details for action
91    """
92    result = haproxy_action_svc.show_action(kwargs['uuid'])
93
94    CliOutputFormatter(result, kwargs['output'], kwargs['cols'].split(",")).echo()
95
96
97@action.command()
98@click.argument('name')
99@click.option(
100    '--description',
101    help=('Description for this rule.'),
102    show_default=True,
103    default=None,
104    required=False,
105)
106@click.option(
107    '--testType',
108    help=(
109        'Choose how to test. By using IF it tests if the condition evaluates to true. '
110        'If you use UNLESS, the sense of the test is reversed.'
111    ),
112    type=click.Choice(['if', 'unless']),
113    multiple=False,
114    callback=tuple_to_csv,
115    show_default=True,
116    default='if',
117    required=True,
118)
119@click.option(
120    '--linkedAcls',
121    help=('Select one or more conditions to be used for this rule.'),
122    callback=resolve_linked_names_to_uuids,
123    show_default=True,
124    default=None,
125    required=False,
126)
127@click.option(
128    '--operator',
129    help=('Choose a logical operator.'),
130    type=click.Choice(['', 'and', 'or']),
131    multiple=False,
132    callback=tuple_to_csv,
133    show_default=True,
134    default='and',
135    required=False,
136)
137@click.option(
138    '--type',
139    help=('Choose a HAProxy function that should be executed if the condition evaluates to true.'),
140    type=click.Choice(
141        [
142            'use_backend', 'use_server', 'map_use_backend', 'http-request_allow', 'http-request_deny',
143            'http-request_tarpit', 'http-request_auth', 'http-request_redirect', 'http-request_lua',
144            'http-request_use-service', 'http-request_add-header', 'http-request_set-header', 'http-request_del-header',
145            'http-request_replace-header', 'http-request_replace-value', 'http-request_set-path',
146            'http-request_set-var', 'http-response_allow', 'http-response_deny', 'http-response_lua',
147            'http-response_add-header', 'http-response_set-header', 'http-response_del-header',
148            'http-response_replace-header', 'http-response_replace-value', 'http-response_set-status',
149            'http-response_set-var', 'tcp-request_connection_accept', 'tcp-request_connection_reject',
150            'tcp-request_content_accept', 'tcp-request_content_reject', 'tcp-request_content_lua',
151            'tcp-request_content_use-service', 'tcp-request_inspect-delay', 'tcp-response_content_accept',
152            'tcp-response_content_close', 'tcp-response_content_reject', 'tcp-response_content_lua',
153            'tcp-response_inspect-delay', 'custom'
154        ]
155    ),
156    multiple=False,
157    callback=tuple_to_csv,
158    show_default=True,
159    default=None,
160    required=True,
161)
162@click.option(
163    '--use_backend',
164    help=('HAProxy will use this backend pool if the condition evaluates to true.'),
165    callback=resolve_linked_names_to_uuids,
166    show_default=True,
167    default=None,
168    required=False,
169)
170@click.option(
171    '--use_server',
172    help=(
173        'HAProxy will use this server instead of other servers that are specified in the Backend Pool. '
174        'The server must exist in the context where this rule is applied.'
175    ),
176    callback=resolve_linked_names_to_uuids,
177    show_default=True,
178    default=None,
179    required=False,
180)
181@click.option(
182    '--http_request_auth',
183    help=(
184        'When HAProxy requests user name and password from the user, this optional authentication realm is returned '
185        'with the response (typically the application\'s name).'
186    ),
187    show_default=True,
188    default=None,
189    required=False,
190)
191@click.option(
192    '--http_request_redirect',
193    help=(
194        'Use HAProxy\'s redirect function to return a HTTP redirection.'
195    ),
196    show_default=True,
197    default=None,
198    required=False,
199)
200@click.option(
201    '--http_request_lua',
202    help=('Execute the specified Lua function. You will most likely need to include/load your Lua code first.'),
203    show_default=True,
204    default=None,
205    required=False,
206)
207@click.option(
208    '--http_request_use_service',
209    help=('Register the specified Lua service. You will most likely need to include/load your Lua code first.'),
210    show_default=True,
211    default=None,
212    required=False,
213)
214@click.option(
215    '--http_request_add_header_name',
216    help=('Append a HTTP header field with the specified name.'),
217    show_default=True,
218    default=None,
219    required=False,
220)
221@click.option(
222    '--http_request_add_header_content',
223    help=(
224        'The value that should be set for the specified HTTP header. '
225        'Note that it is possible to use pre-defined variables.'
226    ),
227    show_default=True,
228    default=None,
229    required=False,
230)
231@click.option(
232    '--http_request_set_header_name',
233    help=(
234        'Remove the HTTP header field with the specified name and add a new one with the same name. '
235        'This is useful when passing security information to the server, '
236        'where the header must not be manipulated by external users.'
237    ),
238    show_default=True,
239    default=None,
240    required=False,
241)
242@click.option(
243    '--http_request_set_header_content',
244    help=(
245        'The value that should be set for the specified HTTP header.'),
246    show_default=True,
247    default=None,
248    required=False,
249)
250@click.option(
251    '--http_request_del_header_name',
252    help=('Remove the HTTP header field with the specified name.'),
253    show_default=True,
254    default=None,
255    required=False,
256)
257@click.option(
258    '--http_request_replace_header_name',
259    help=('The name of the HTTP header field.'),
260    show_default=True,
261    default=None,
262    required=False,
263)
264@click.option(
265    '--http_request_replace_header_regex',
266    help=('Matches the specified regular expression in all occurrences of the header field.'),
267    show_default=True,
268    default=None,
269    required=False,
270)
271@click.option(
272    '--http_request_replace_value_name',
273    help=('The name of the HTTP header field.'),
274    show_default=True,
275    default=None,
276    required=False,
277)
278@click.option(
279    '--http_request_replace_value_regex',
280    help=(
281        'This is suited for all header fields which are allowed to carry more than one value: '
282        'Matches the specified regular expression against every comma-delimited value of the header field.'
283    ),
284    show_default=True,
285    default=None,
286    required=False,
287)
288@click.option(
289    '--http_request_set_path',
290    help=(
291        'Rewrites the request path. The query string, if any, is left intact. '
292        'If a scheme and authority is found before the path, they are left intact as well.'
293    ),
294    show_default=True,
295    default=None,
296    required=False,
297)
298@click.option(
299    '--http_request_set_var_scope',
300    help=('The name of the variable starts with an indication about its scope.'),
301    type=click.Choice(['', 'proc', 'sess', 'txn', 'req', 'res']),
302    multiple=False,
303    callback=tuple_to_csv,
304    show_default=True,
305    default='txn',
306    required=False,
307)
308@click.option(
309    '--http_request_set_var_name',
310    help=('None'),
311    show_default=True,
312    default=None,
313    required=False,
314)
315@click.option(
316    '--http_request_set_var_expr',
317    help=('A standard HAProxy expression formed by a sample-fetch followed by some converters.'),
318    show_default=True,
319    default=None,
320    required=False,
321)
322@click.option(
323    '--http_response_lua',
324    help=('Execute the specified Lua function. You will most likely need to include/load your Lua code first.'),
325    show_default=True,
326    default=None,
327    required=False,
328)
329@click.option(
330    '--http_response_add_header_name',
331    help=('Append a HTTP header field with the specified name.'),
332    show_default=True,
333    default=None,
334    required=False,
335)
336@click.option(
337    '--http_response_add_header_content',
338    help=(
339        'The value that should be set for the specified HTTP header. '
340        'Note that it\'s possible to use pre-defined variables'
341    ),
342    show_default=True,
343    default=None,
344    required=False,
345)
346@click.option(
347    '--http_response_set_header_name',
348    help=(
349        'Remove the HTTP header field with the specified name and add a new one with the same name. '
350        'This is useful when passing security information to the server, '
351        'where the header must not be manipulated by external users.'
352    ),
353    show_default=True,
354    default=None,
355    required=False,
356)
357@click.option(
358    '--http_response_set_header_content',
359    help=(
360        'The value that should be set for the specified HTTP header. '
361        'Note that it\'s possible to use pre-defined variables'
362    ),
363    show_default=True,
364    default=None,
365    required=False,
366)
367@click.option(
368    '--http_response_del_header_name',
369    help=('Remove the HTTP header field with the specified name.'),
370    show_default=True,
371    default=None,
372    required=False,
373)
374@click.option(
375    '--http_response_replace_header_name',
376    help=('The name of the HTTP header field.'),
377    show_default=True,
378    default=None,
379    required=False,
380)
381@click.option(
382    '--http_response_replace_header_regex',
383    help=('Matches the specified regular expression in all occurrences of header field.'),
384    show_default=True,
385    default=None,
386    required=False,
387)
388@click.option(
389    '--http_response_replace_value_name',
390    help=('The name of the HTTP header field.'),
391    show_default=True,
392    default=None,
393    required=False,
394)
395@click.option(
396    '--http_response_replace_value_regex',
397    help=(
398        'This is suited for all header fields which are allowed to carry more than one value: '
399        'Matches the specified regular expression against every comma-delimited value of the header field.'
400    ),
401    show_default=True,
402    default=None,
403    required=False,
404)
405@click.option(
406    '--http_response_set_status_code',
407    help=('Replaces the response status code. Must be an integer between 100 and 999.'),
408    show_default=True,
409    type=INT_OR_EMPTY,
410    callback=int_as_string,
411    default=None,
412    required=False,
413)
414@click.option(
415    '--http_response_set_status_reason',
416    help=(
417        'An optional custom reason text for the HTTP status code. '
418        'If empty the default reason for the specified code will be used.'
419    ),
420    show_default=True,
421    default=None,
422    required=False,
423)
424@click.option(
425    '--http_response_set_var_scope',
426    help=('The name of the variable starts with an indication about its scope.'),
427    type=click.Choice(['', 'proc', 'sess', 'txn', 'req', 'res']),
428    multiple=False,
429    callback=tuple_to_csv,
430    show_default=True,
431    default='txn',
432    required=False,
433)
434@click.option(
435    '--http_response_set_var_name',
436    help=('None'),
437    show_default=True,
438    default=None,
439    required=False,
440)
441@click.option(
442    '--http_response_set_var_expr',
443    help=('A standard HAProxy expression formed by a sample-fetch followed by some converters.'),
444    show_default=True,
445    default=None,
446    required=False,
447)
448@click.option(
449    '--tcp_request_content_lua',
450    help=('Execute the specified Lua function. You will most likely need to include/load your Lua code first.'),
451    show_default=True,
452    default=None,
453    required=False,
454)
455@click.option(
456    '--tcp_request_content_use_service',
457    help=('Register the specified Lua service. You will most likely need to include/load your Lua code first.'),
458    show_default=True,
459    default=None,
460    required=False,
461)
462@click.option(
463    '--tcp_request_inspect_delay',
464    help=(
465        'Set the maximum allowed time to wait for data during content inspection. '
466        'Defaults to milliseconds. You may also enter a number followed by one of the supported suffixes '
467        '"d" (days), "h" (hour), "m" (minute), "s" (seconds), "ms" (miliseconds).'
468    ),
469    show_default=True,
470    default=None,
471    required=False,
472)
473@click.option(
474    '--tcp_response_content_lua',
475    help=('Execute the specified Lua function. You will most likely need to include/load your Lua code first.'),
476    show_default=True,
477    default=None,
478    required=False,
479)
480@click.option(
481    '--tcp_response_inspect_delay',
482    help=(
483        'Set the maximum allowed time to wait for a response during content inspection. '
484        'Defaults to milliseconds. You may also enter a number followed by one of the supported suffixes '
485        '"d" (days), "h" (hour), "m" (minute), "s" (seconds), "ms" (miliseconds).'
486    ),
487    show_default=True,
488    default=None,
489    required=False,
490)
491@click.option(
492    '--custom',
493    help=('Specify a HAProxy rule/ACL that is currently not supported by the GUI.'),
494    show_default=True,
495    default=None,
496    required=False,
497)
498@click.option(
499    '--useBackend',
500    help=('None'),
501    callback=resolve_linked_names_to_uuids,
502    show_default=True,
503    default=None,
504    required=False,
505)
506@click.option(
507    '--useServer',
508    help=('None'),
509    callback=resolve_linked_names_to_uuids,
510    show_default=True,
511    default=None,
512    required=False,
513)
514@click.option(
515    '--actionName',
516    help=('None'),
517    show_default=True,
518    default=None,
519    required=False,
520)
521@click.option(
522    '--actionFind',
523    help=('None'),
524    show_default=True,
525    default=None,
526    required=False,
527)
528@click.option(
529    '--actionValue',
530    help=('None'),
531    show_default=True,
532    default=None,
533    required=False,
534)
535@click.option(
536    '--map_use_backend_file',
537    help=(
538        'HAProxy will extract the Host header from the HTTP request and search the map file for a match. '
539        'If a match is found, the backend pool from the map file will be used.'
540    ),
541    callback=resolve_linked_names_to_uuids,
542    show_default=True,
543    default=None,
544    required=False,
545)
546@click.option(
547    '--map_use_backend_default',
548    help=('HAProxy will use this backend pool if no match is found in the map file.'),
549    callback=resolve_linked_names_to_uuids,
550    show_default=True,
551    default=None,
552    required=False,
553)
554@click.option(
555    '--output', '-o',
556    help='Specifies the Output format.',
557    default="plain",
558    type=click.Choice(available_formats()),
559    callback=formatter_from_formatter_name,
560    show_default=True,
561)
562@click.option(
563    '--cols', '-c',
564    help='Which columns should be printed? Pass empty string (-c '') to show all columns',
565    default="result,validations",
566    show_default=True,
567)
568@pass_haproxy_action_svc
569def create(haproxy_action_svc: HaproxyActionFacade, **kwargs):
570    """
571    Create a new action
572    """
573    json_payload = {
574        'action': {
575            "name": kwargs['name'],
576            "description": kwargs['description'],
577            "testType": kwargs['testtype'],
578            "linkedAcls": kwargs['linkedacls'],
579            "operator": kwargs['operator'],
580            "type": kwargs['type'],
581            "use_backend": kwargs['use_backend'],
582            "use_server": kwargs['use_server'],
583            "http_request_auth": kwargs['http_request_auth'],
584            "http_request_redirect": kwargs['http_request_redirect'],
585            "http_request_lua": kwargs['http_request_lua'],
586            "http_request_use_service": kwargs['http_request_use_service'],
587            "http_request_add_header_name": kwargs['http_request_add_header_name'],
588            "http_request_add_header_content": kwargs['http_request_add_header_content'],
589            "http_request_set_header_name": kwargs['http_request_set_header_name'],
590            "http_request_set_header_content": kwargs['http_request_set_header_content'],
591            "http_request_del_header_name": kwargs['http_request_del_header_name'],
592            "http_request_replace_header_name": kwargs['http_request_replace_header_name'],
593            "http_request_replace_header_regex": kwargs['http_request_replace_header_regex'],
594            "http_request_replace_value_name": kwargs['http_request_replace_value_name'],
595            "http_request_replace_value_regex": kwargs['http_request_replace_value_regex'],
596            "http_request_set_path": kwargs['http_request_set_path'],
597            "http_request_set_var_scope": kwargs['http_request_set_var_scope'],
598            "http_request_set_var_name": kwargs['http_request_set_var_name'],
599            "http_request_set_var_expr": kwargs['http_request_set_var_expr'],
600            "http_response_lua": kwargs['http_response_lua'],
601            "http_response_add_header_name": kwargs['http_response_add_header_name'],
602            "http_response_add_header_content": kwargs['http_response_add_header_content'],
603            "http_response_set_header_name": kwargs['http_response_set_header_name'],
604            "http_response_set_header_content": kwargs['http_response_set_header_content'],
605            "http_response_del_header_name": kwargs['http_response_del_header_name'],
606            "http_response_replace_header_name": kwargs['http_response_replace_header_name'],
607            "http_response_replace_header_regex": kwargs['http_response_replace_header_regex'],
608            "http_response_replace_value_name": kwargs['http_response_replace_value_name'],
609            "http_response_replace_value_regex": kwargs['http_response_replace_value_regex'],
610            "http_response_set_status_code": kwargs['http_response_set_status_code'],
611            "http_response_set_status_reason": kwargs['http_response_set_status_reason'],
612            "http_response_set_var_scope": kwargs['http_response_set_var_scope'],
613            "http_response_set_var_name": kwargs['http_response_set_var_name'],
614            "http_response_set_var_expr": kwargs['http_response_set_var_expr'],
615            "tcp_request_content_lua": kwargs['tcp_request_content_lua'],
616            "tcp_request_content_use_service": kwargs['tcp_request_content_use_service'],
617            "tcp_request_inspect_delay": kwargs['tcp_request_inspect_delay'],
618            "tcp_response_content_lua": kwargs['tcp_response_content_lua'],
619            "tcp_response_inspect_delay": kwargs['tcp_response_inspect_delay'],
620            "custom": kwargs['custom'],
621            "useBackend": kwargs['usebackend'],
622            "useServer": kwargs['useserver'],
623            "actionName": kwargs['actionname'],
624            "actionFind": kwargs['actionfind'],
625            "actionValue": kwargs['actionvalue'],
626            "map_use_backend_file": kwargs['map_use_backend_file'],
627            "map_use_backend_default": kwargs['map_use_backend_default'],
628        }
629    }
630
631    result = haproxy_action_svc.create_action(json_payload)
632
633    CliOutputFormatter(result, kwargs['output'], kwargs['cols'].split(",")).echo()
634
635
636@action.command()
637@click.argument('uuid')
638@click.option(
639    '--name',
640    help=('Name to identify this rule.'),
641    show_default=True,
642    default=None
643)
644@click.option(
645    '--description',
646    help=('Description for this rule.'),
647    show_default=True,
648    default=None
649)
650@click.option(
651    '--testType',
652    help=(
653        'Choose how to test. By using IF it tests if the condition evaluates to true. '
654        'If you use UNLESS, the sense of the test is reversed.'
655    ),
656    type=click.Choice(['if', 'unless']),
657    multiple=False,
658    callback=tuple_to_csv,
659    show_default=True,
660    default=None
661)
662@click.option(
663    '--linkedAcls',
664    help=('Select one or more conditions to be used for this rule.'),
665    callback=resolve_linked_names_to_uuids,
666    show_default=True,
667    default=None
668)
669@click.option(
670    '--operator',
671    help=('Choose a logical operator.'),
672    type=click.Choice(['', 'and', 'or']),
673    multiple=False,
674    callback=tuple_to_csv,
675    show_default=True,
676    default=None
677)
678@click.option(
679    '--type',
680    help=('Choose a HAProxy function that should be executed if the condition evaluates to true.'),
681    type=click.Choice(
682        [
683            'use_backend', 'use_server', 'map_use_backend', 'http-request_allow', 'http-request_deny',
684            'http-request_tarpit', 'http-request_auth', 'http-request_redirect', 'http-request_lua',
685            'http-request_use-service', 'http-request_add-header', 'http-request_set-header',
686            'http-request_del-header', 'http-request_replace-header', 'http-request_replace-value',
687            'http-request_set-path', 'http-request_set-var', 'http-response_allow', 'http-response_deny',
688            'http-response_lua', 'http-response_add-header', 'http-response_set-header', 'http-response_del-header',
689            'http-response_replace-header', 'http-response_replace-value', 'http-response_set-status',
690            'http-response_set-var', 'tcp-request_connection_accept', 'tcp-request_connection_reject',
691            'tcp-request_content_accept', 'tcp-request_content_reject', 'tcp-request_content_lua',
692            'tcp-request_content_use-service', 'tcp-request_inspect-delay', 'tcp-response_content_accept',
693            'tcp-response_content_close', 'tcp-response_content_reject', 'tcp-response_content_lua',
694            'tcp-response_inspect-delay', 'custom'
695        ]
696    ),
697    multiple=False,
698    callback=tuple_to_csv,
699    show_default=True,
700    default=None
701)
702@click.option(
703    '--use_backend',
704    help=('HAProxy will use this backend pool if the condition evaluates to true.'),
705    callback=resolve_linked_names_to_uuids,
706    show_default=True,
707    default=None
708)
709@click.option(
710    '--use_server',
711    help=(
712        'HAProxy will use this server instead of other servers that are specified in the Backend Pool. '
713        'The server must exist in the context where this rule is applied.'
714    ),
715    callback=resolve_linked_names_to_uuids,
716    show_default=True,
717    default=None
718)
719@click.option(
720    '--http_request_auth',
721    help=(
722        'When HAProxy requests user name and password from the user, this optional authentication realm '
723        'is returned with the response (typically the application\'s name).'
724    ),
725    show_default=True,
726    default=None
727)
728@click.option(
729    '--http_request_redirect',
730    help=(
731        'Use HAProxy\'s redirect function to return a HTTP redirection.'
732    ),
733    show_default=True,
734    default=None
735)
736@click.option(
737    '--http_request_lua',
738    help=('Execute the specified Lua function. You will most likely need to include/load your Lua code first.'),
739    show_default=True,
740    default=None
741)
742@click.option(
743    '--http_request_use_service',
744    help=('Register the specified Lua service. You will most likely need to include/load your Lua code first.'),
745    show_default=True,
746    default=None
747)
748@click.option(
749    '--http_request_add_header_name',
750    help=('Append a HTTP header field with the specified name.'),
751    show_default=True,
752    default=None
753)
754@click.option(
755    '--http_request_add_header_content',
756    help=(
757        'The value that should be set for the specified HTTP header. '
758        'Note that it is possible to use pre-defined variables.'),
759    show_default=True,
760    default=None
761)
762@click.option(
763    '--http_request_set_header_name',
764    help=(
765        'Remove the HTTP header field with the specified name and add a new one with the same name. '
766        'This is useful when passing security information to the server, '
767        'where the header must not be manipulated by external users.'
768    ),
769    show_default=True,
770    default=None
771)
772@click.option(
773    '--http_request_set_header_content',
774    help=(
775        'The value that should be set for the specified HTTP header. '
776        'Note that it\'s possible to use pre-defined variables.'
777    ),
778    show_default=True,
779    default=None
780)
781@click.option(
782    '--http_request_del_header_name',
783    help=('Remove the HTTP header field with the specified name.'),
784    show_default=True,
785    default=None
786)
787@click.option(
788    '--http_request_replace_header_name',
789    help=('The name of the HTTP header field.'),
790    show_default=True,
791    default=None
792)
793@click.option(
794    '--http_request_replace_header_regex',
795    help=('Matches the specified regular expression in all occurrences of the header field.'),
796    show_default=True,
797    default=None
798)
799@click.option(
800    '--http_request_replace_value_name',
801    help=('The name of the HTTP header field.'),
802    show_default=True,
803    default=None
804)
805@click.option(
806    '--http_request_replace_value_regex',
807    help=(
808        'This is suited for all header fields which are allowed to carry more than one value: '
809        'Matches the specified regular expression against every comma-delimited value of the header field.'
810    ),
811    show_default=True,
812    default=None
813)
814@click.option(
815    '--http_request_set_path',
816    help=(
817        'Rewrites the request path. The query string, if any, is left intact. '
818        'If a scheme and authority is found before the path, they are left intact as well.'
819    ),
820    show_default=True,
821    default=None
822)
823@click.option(
824    '--http_request_set_var_scope',
825    help=('The name of the variable starts with an indication about its scope.'),
826    type=click.Choice(['', 'proc', 'sess', 'txn', 'req', 'res']),
827    multiple=False,
828    callback=tuple_to_csv,
829    show_default=True,
830    default=None
831)
832@click.option(
833    '--http_request_set_var_name',
834    help=('None'),
835    show_default=True,
836    default=None
837)
838@click.option(
839    '--http_request_set_var_expr',
840    help=('A standard HAProxy expression formed by a sample-fetch followed by some converters.'),
841    show_default=True,
842    default=None
843)
844@click.option(
845    '--http_response_lua',
846    help=('Execute the specified Lua function. You will most likely need to include/load your Lua code first.'),
847    show_default=True,
848    default=None
849)
850@click.option(
851    '--http_response_add_header_name',
852    help=('Append a HTTP header field with the specified name.'),
853    show_default=True,
854    default=None
855)
856@click.option(
857    '--http_response_add_header_content',
858    help=(
859        'The value that should be set for the specified HTTP header. '
860        'Note that it\'s possible to use pre-defined variables.'
861    ),
862    show_default=True,
863    default=None
864)
865@click.option(
866    '--http_response_set_header_name',
867    help=(
868        'Remove the HTTP header field with the specified name and add a new one with the same name. '
869        'This is useful when passing security information to the server, '
870        'where the header must not be manipulated by external users.'
871    ),
872    show_default=True,
873    default=None
874)
875@click.option(
876    '--http_response_set_header_content',
877    help=(
878        'The value that should be set for the specified HTTP header. '
879        'Note that it\'s possible to use pre-defined variables.'
880    ),
881    show_default=True,
882    default=None
883)
884@click.option(
885    '--http_response_del_header_name',
886    help=('Remove the HTTP header field with the specified name.'),
887    show_default=True,
888    default=None
889)
890@click.option(
891    '--http_response_replace_header_name',
892    help=('The name of the HTTP header field.'),
893    show_default=True,
894    default=None
895)
896@click.option(
897    '--http_response_replace_header_regex',
898    help=('Matches the specified regular expression in all occurrences of header field.'),
899    show_default=True,
900    default=None
901)
902@click.option(
903    '--http_response_replace_value_name',
904    help=('The name of the HTTP header field.'),
905    show_default=True,
906    default=None
907)
908@click.option(
909    '--http_response_replace_value_regex',
910    help=(
911        'This is suited for all header fields which are allowed to carry more than one value: '
912        'Matches the specified regular expression against every comma-delimited value of the header field.'
913    ),
914    show_default=True,
915    default=None
916)
917@click.option(
918    '--http_response_set_status_code',
919    help=('Replaces the response status code. Must be an integer between 100 and 999.'),
920    show_default=True,
921    type=INT_OR_EMPTY,
922    callback=int_as_string,
923    default=None
924)
925@click.option(
926    '--http_response_set_status_reason',
927    help=(
928        'An optional custom reason text for the HTTP status code. '
929        'If empty the default reason for the specified code will be used.'
930    ),
931    show_default=True,
932    default=None
933)
934@click.option(
935    '--http_response_set_var_scope',
936    help=('The name of the variable starts with an indication about its scope.'),
937    type=click.Choice(['', 'proc', 'sess', 'txn', 'req', 'res']),
938    multiple=False,
939    callback=tuple_to_csv,
940    show_default=True,
941    default=None
942)
943@click.option(
944    '--http_response_set_var_name',
945    help=('None'),
946    show_default=True,
947    default=None
948)
949@click.option(
950    '--http_response_set_var_expr',
951    help=('A standard HAProxy expression formed by a sample-fetch followed by some converters.'),
952    show_default=True,
953    default=None
954)
955@click.option(
956    '--tcp_request_content_lua',
957    help=('Execute the specified Lua function. You will most likely need to include/load your Lua code first.'),
958    show_default=True,
959    default=None
960)
961@click.option(
962    '--tcp_request_content_use_service',
963    help=('Register the specified Lua service. You will most likely need to include/load your Lua code first.'),
964    show_default=True,
965    default=None
966)
967@click.option(
968    '--tcp_request_inspect_delay',
969    help=(
970        'Set the maximum allowed time to wait for data during content inspection. '
971        'Defaults to milliseconds. You may also enter a number followed by one of the supported suffixes '
972        '"d" (days), "h" (hour), "m" (minute), "s" (seconds), "ms" (miliseconds).'
973    ),
974    show_default=True,
975    default=None
976)
977@click.option(
978    '--tcp_response_content_lua',
979    help=('Execute the specified Lua function. You will most likely need to include/load your Lua code first.'),
980    show_default=True,
981    default=None
982)
983@click.option(
984    '--tcp_response_inspect_delay',
985    help=(
986        'Set the maximum allowed time to wait for a response during content inspection. '
987        'Defaults to milliseconds. You may also enter a number followed by one of the supported suffixes '
988        '"d" (days), "h" (hour), "m" (minute), "s" (seconds), "ms" (miliseconds).'
989    ),
990    show_default=True,
991    default=None
992)
993@click.option(
994    '--custom',
995    help=('Specify a HAProxy rule/ACL that is currently not supported by the GUI.'),
996    show_default=True,
997    default=None
998)
999@click.option(
1000    '--useBackend',
1001    help=('None'),
1002    callback=resolve_linked_names_to_uuids,
1003    show_default=True,
1004    default=None
1005)
1006@click.option(
1007    '--useServer',
1008    help=('None'),
1009    callback=resolve_linked_names_to_uuids,
1010    show_default=True,
1011    default=None
1012)
1013@click.option(
1014    '--actionName',
1015    help=('None'),
1016    show_default=True,
1017    default=None
1018)
1019@click.option(
1020    '--actionFind',
1021    help=('None'),
1022    show_default=True,
1023    default=None
1024)
1025@click.option(
1026    '--actionValue',
1027    help=('None'),
1028    show_default=True,
1029    default=None
1030)
1031@click.option(
1032    '--map_use_backend_file',
1033    help=(
1034        'HAProxy will extract the Host header from the HTTP request and search the map file for a match. '
1035        'If a match is found, the backend pool from the map file will be used.'
1036    ),
1037    callback=resolve_linked_names_to_uuids,
1038    show_default=True,
1039    default=None
1040)
1041@click.option(
1042    '--map_use_backend_default',
1043    help=('HAProxy will use this backend pool if no match is found in the map file.'),
1044    callback=resolve_linked_names_to_uuids,
1045    show_default=True,
1046    default=None
1047)
1048@click.option(
1049    '--output', '-o',
1050    help='Specifies the Output format.',
1051    default="plain",
1052    type=click.Choice(available_formats()),
1053    callback=formatter_from_formatter_name,
1054    show_default=True,
1055)
1056@click.option(
1057    '--cols', '-c',
1058    help='Which columns should be printed? Pass empty string (-c '') to show all columns',
1059    default="result,validations",
1060    show_default=True,
1061)
1062@pass_haproxy_action_svc
1063def update(haproxy_action_svc: HaproxyActionFacade, **kwargs):
1064    """
1065    Update a action.
1066    """
1067    json_payload = {
1068        'action': {}
1069    }
1070    options = [
1071        'name', 'description', 'testType', 'linkedAcls', 'operator', 'type', 'use_backend', 'use_server',
1072        'http_request_auth', 'http_request_redirect', 'http_request_lua', 'http_request_use_service',
1073        'http_request_add_header_name', 'http_request_add_header_content', 'http_request_set_header_name',
1074        'http_request_set_header_content', 'http_request_del_header_name', 'http_request_replace_header_name',
1075        'http_request_replace_header_regex', 'http_request_replace_value_name', 'http_request_replace_value_regex',
1076        'http_request_set_path', 'http_request_set_var_scope', 'http_request_set_var_name',
1077        'http_request_set_var_expr', 'http_response_lua', 'http_response_add_header_name',
1078        'http_response_add_header_content', 'http_response_set_header_name', 'http_response_set_header_content',
1079        'http_response_del_header_name', 'http_response_replace_header_name', 'http_response_replace_header_regex',
1080        'http_response_replace_value_name', 'http_response_replace_value_regex', 'http_response_set_status_code',
1081        'http_response_set_status_reason', 'http_response_set_var_scope', 'http_response_set_var_name',
1082        'http_response_set_var_expr', 'tcp_request_content_lua', 'tcp_request_content_use_service',
1083        'tcp_request_inspect_delay', 'tcp_response_content_lua', 'tcp_response_inspect_delay',
1084        'custom', 'useBackend', 'useServer', 'actionName', 'actionFind', 'actionValue',
1085        'map_use_backend_file', 'map_use_backend_default'
1086    ]
1087    for option in options:
1088        if kwargs[option.lower()] is not None:
1089            json_payload['action'][option] = kwargs[option.lower()]
1090
1091    result = haproxy_action_svc.update_action(kwargs['uuid'], json_payload)
1092
1093    CliOutputFormatter(result, kwargs['output'], kwargs['cols'].split(",")).echo()
1094
1095
1096@action.command()
1097@click.argument('uuid')
1098@click.option(
1099    '--output', '-o',
1100    help='Specifies the Output format.',
1101    default="plain",
1102    type=click.Choice(available_formats()),
1103    callback=formatter_from_formatter_name,
1104    show_default=True,
1105)
1106@click.option(
1107    '--cols', '-c',
1108    help='Which columns should be printed? Pass empty string (-c '') to show all columns',
1109    default="result,validations",
1110    show_default=True,
1111)
1112@pass_haproxy_action_svc
1113def delete(haproxy_action_svc: HaproxyActionFacade, **kwargs):
1114    """
1115    Delete action
1116    """
1117    result = haproxy_action_svc.delete_action(kwargs['uuid'])
1118
1119    CliOutputFormatter(result, kwargs['output'], kwargs['cols'].split(",")).echo()
1120