Fixes some bugs and things (#35122)

Removes deprecations and fixes bugs.
pull/35138/head
Tim Rupp 7 years ago committed by GitHub
parent a0bb193598
commit ca8982f96c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -427,14 +427,6 @@ class ArgumentSpec(object):
type='str',
default='rest',
choices=['cli', 'rest']
),
password=dict(
fallback=(env_fallback, ['F5_PASSWORD']),
no_log=True
),
partition=dict(
default='Common',
fallback=(env_fallback, ['F5_PARTITION'])
)
)
self.argument_spec = {}

@ -492,12 +492,9 @@ class ModuleManager(object):
return False
def exec_module(self):
changed = False
result = dict()
state = self.want.state
try:
if state == "present":
changed = self.update()
except iControlUnexpectedHTTPError as e:
raise F5ModuleError(str(e))
@ -556,11 +553,7 @@ class ArgumentSpec(object):
),
mirror_primary_address=dict(),
mirror_secondary_address=dict(),
config_sync_ip=dict(),
state=dict(
default='present',
choices=['present']
)
config_sync_ip=dict()
)
self.argument_spec = {}
self.argument_spec.update(f5_argument_spec)

@ -27,7 +27,7 @@ options:
choices:
- pool
- wide_ip
- virtual_server
- server
filter:
description:
- Perform regex filter of response. Filtering is done on the name of
@ -117,13 +117,13 @@ pool:
ttl: 30
type: naptr
verify_member_availability: disabled
virtual_server:
server:
description:
Contains the virtual server enabled and availability status, and address.
returned: changed
type: list
sample:
virtual_server:
server:
- addresses:
- device_name: /Common/qweqwe
name: 10.10.10.10
@ -231,10 +231,6 @@ class BaseManager(object):
srvs='srv'
)
def exec_module(self):
result = self.read_current_from_device()
return result
def filter_matches_name(self, name):
if self.want.filter is None:
return True
@ -270,7 +266,8 @@ class UntypedManager(BaseManager):
results = []
facts = self.read_facts()
for item in facts:
filtered = [(k, v) for k, v in iteritems(item) if self.filter_matches_name(k)]
attrs = item.to_return()
filtered = [(k, v) for k, v in iteritems(attrs) if self.filter_matches_name(k)]
if filtered:
results.append(dict(filtered))
return results
@ -297,19 +294,12 @@ class Parameters(AnsibleF5Parameters):
@property
def include(self):
requested = self._values['include']
valid = ['pool', 'wide_ip', 'virtual_server', 'server', 'all']
valid = ['pool', 'wide_ip', 'server', 'all']
if any(x for x in requested if x not in valid):
raise F5ModuleError(
"The valid 'include' choices are {0}".format(', '.join(valid))
)
if any(x for x in requested if x == 'virtual_server'):
self._values['__warnings'].append(
dict(
msg="The 'virtual_server' param is deprecated. Use 'server' instead",
version='2.5'
)
)
if 'all' in requested:
return ['all']
@ -337,9 +327,11 @@ class BaseParameters(Parameters):
return False
def _remove_internal_keywords(self, resource):
del resource['kind']
del resource['generation']
del resource['selfLink']
resource.pop('kind', None)
resource.pop('generation', None)
resource.pop('selfLink', None)
resource.pop('isSubcollection', None)
resource.pop('fullPath', None)
def to_return(self):
result = {}
@ -653,7 +645,7 @@ class ServerParameters(BaseParameters):
if 'translationAddress' in item:
item['translation_address'] = item.pop('translationAddress')
if 'translationPort' in item:
item['translation_port'] = int(item.pop('translation_port'))
item['translation_port'] = int(item.pop('translationPort'))
result.append(item)
return result
@ -724,7 +716,7 @@ class TypedPoolFactManager(TypedManager):
for resource in collection:
attrs = resource.attrs
attrs['stats'] = self.read_stats_from_device(resource)
params = PoolParameters(attrs)
params = PoolParameters(params=attrs)
results.append(params)
return results
@ -752,7 +744,7 @@ class UntypedPoolFactManager(UntypedManager):
for resource in collection:
attrs = resource.attrs
attrs['stats'] = self.read_stats_from_device(resource)
params = PoolParameters(attrs)
params = PoolParameters(params=attrs)
results.append(params)
return results
@ -794,7 +786,7 @@ class TypedWideIpFactManager(TypedManager):
collection = self.read_collection_from_device(collection)
for resource in collection:
attrs = resource.attrs
params = WideIpParameters(attrs)
params = WideIpParameters(params=attrs)
results.append(params)
return results
@ -821,7 +813,7 @@ class UntypedWideIpFactManager(UntypedManager):
collection = self.read_collection_from_device()
for resource in collection:
attrs = resource.attrs
params = WideIpParameters(attrs)
params = WideIpParameters(params=attrs)
results.append(params)
return results
@ -843,7 +835,7 @@ class ServerFactManager(UntypedManager):
def exec_module(self):
facts = super(ServerFactManager, self).exec_module()
result = dict(server=facts, virtual_server=facts)
result = dict(server=facts)
return result
def read_facts(self):
@ -851,7 +843,7 @@ class ServerFactManager(UntypedManager):
collection = self.read_collection_from_device()
for resource in collection:
attrs = resource.attrs
params = WideIpParameters(attrs)
params = ServerParameters(params=attrs)
results.append(params)
return results
@ -881,10 +873,6 @@ class ModuleManager(object):
names = ['pool', 'wide_ip', 'server']
else:
names = self.want.include
# The virtual_server parameter is deprecated
if 'virtual_server' in names:
names.append('server')
names.remove('virtual_server')
managers = [self.get_manager(name) for name in names]
result = self.execute_managers(managers)
if result:

@ -78,6 +78,8 @@ options:
- foundry-server-iron
- netapp
- windows-2000-server
aliases:
- product
link_discovery:
description:
- Specifies whether the system auto-discovers the links for this server. When

@ -23,8 +23,6 @@ options:
description:
- Monitor name.
required: True
aliases:
- monitor
parent:
description:
- The parent template of this monitor template. Once this value has

@ -23,8 +23,6 @@ options:
description:
- Monitor name.
required: True
aliases:
- monitor
parent:
description:
- The parent template of this monitor template. Once this value has

@ -26,8 +26,6 @@ options:
description:
- Monitor name.
required: True
aliases:
- monitor
description:
description:
- Specifies descriptive text that identifies the monitor.
@ -400,13 +398,6 @@ class Difference(object):
"The parent monitor cannot be changed"
)
@property
def destination(self):
if self.want.ip is None:
return None
if self.want.destination != self.have.destination:
return self.want.destination
@property
def interval(self):
if self.want.timeout is not None and self.want.interval is not None:
@ -613,7 +604,6 @@ class ArgumentSpec(object):
name=dict(required=True),
description=dict(),
parent=dict(default='/Common/snmp_dca'),
ip=dict(),
interval=dict(type='int'),
timeout=dict(type='int'),
time_until_up=dict(type='int'),

@ -23,8 +23,6 @@ options:
description:
- Monitor name.
required: True
aliases:
- monitor
parent:
description:
- The parent template of this monitor template. Once this value has
@ -44,19 +42,6 @@ options:
'*'.
- If this value is an IP address, and the C(type) is C(tcp) (the default),
then a C(port) number must be specified.
type:
description:
- The template type of this monitor template.
- Deprecated in 2.4. Use one of the C(bigip_monitor_tcp_echo) or
C(bigip_monitor_tcp_half_open) modules instead.
default: tcp
choices:
- tcp
- tcp_echo
- tcp_half_open
- TTYPE_TCP
- TTYPE_TCP_ECHO
- TTYPE_TCP_HALF_OPEN
port:
description:
- Port address part of the IP/port definition. If this parameter is not

@ -23,8 +23,6 @@ options:
description:
- Monitor name.
required: True
aliases:
- monitor
parent:
description:
- The parent template of this monitor template. Once this value has

@ -23,8 +23,6 @@ options:
description:
- Monitor name.
required: True
aliases:
- monitor
parent:
description:
- The parent template of this monitor template. Once this value has

@ -23,8 +23,6 @@ options:
description:
- Monitor name.
required: True
aliases:
- monitor
parent:
description:
- The parent template of this monitor template. Once this value has

@ -20,6 +20,10 @@ description:
- Manage BIG-IP partitions.
version_added: "2.5"
options:
name:
description:
- Name of the partition
required: True
description:
description:
- The description to attach to the Partition.

@ -20,6 +20,9 @@ description:
- This module will manage LTM policy rules on a BIG-IP.
version_added: 2.5
options:
description:
description:
- Description of the policy rule.
actions:
description:
- The actions that you want the policy rule to perform.

@ -57,18 +57,24 @@ options:
- weighted-least-connections-nod
monitor_type:
description:
- Monitor rule type when C(monitors) is specified. When creating a new
pool, if this value is not specified, the default of 'and_list' will
be used.
- Monitor rule type when C(monitors) is specified.
- When creating a new pool, if this value is not specified, the default
of 'and_list' will be used.
- When C(single) ensures that all specified monitors are checked, but
additionally includes checks to make sure you only specified a single
monitor.
- When C(and_list) ensures that B(all) monitors are checked.
- When C(m_of_n) ensures that C(quorum) of C(monitors) are checked. C(m_of_n)
B(requires) that a C(quorum) of 1 or greater be set either in the playbook,
or already existing on the device.
- Both C(single) and C(and_list) are functionally identical since BIG-IP
considers all monitors as "a list". BIG=IP either has a list of many,
or it has a list of one. Where they differ is in the extra guards that
C(single) provides; namely that it only allows a single monitor.
considers all monitors as "a list".
version_added: "1.3"
choices: ['and_list', 'm_of_n', 'single']
quorum:
description:
- Monitor quorum value when C(monitor_type) is C(m_of_n).
- Quorum must be a value of 1 or greater when C(monitor_type) is C(m_of_n).
version_added: "1.3"
monitors:
description:
@ -99,7 +105,17 @@ options:
- Device partition to manage resources on.
default: Common
version_added: 2.5
metdata:
state:
description:
- When C(present), guarantees that the pool exists with the provided
attributes.
- When C(absent), removes the pool from the system.
default: present
choices:
- absent
- present
version_added: 2.5
metadata:
description:
- Arbitrary key/value pairs that you can attach to a pool. This is useful in
situations where you might want to annotate a pool to me managed by Ansible.
@ -521,6 +537,15 @@ class ReportableChanges(Changes):
result = sorted(re.findall(r'/\w+/[^\s}]+', self._values['monitors']))
return result
@property
def monitor_type(self):
pattern = r'min\s+\d+\s+of'
matches = re.search(pattern, self._values['monitors'])
if matches:
return 'm_of_n'
else:
return 'and_list'
@property
def metadata(self):
result = dict()
@ -569,16 +594,29 @@ class Difference(object):
else:
return want
@property
def monitor_type(self):
def _monitors_and_quorum(self):
if self.want.monitor_type is None:
self.want.update(dict(monitor_type=self.have.monitor_type))
if self.want.monitor_type == 'm_of_n':
if self.want.quorum is None:
self.want.update(dict(quorum=self.have.quorum))
if self.want.monitor_type == 'm_of_n' and self.want.quorum is None:
if self.want.quorum is None or self.want.quorum < 1:
raise F5ModuleError(
"Quorum value must be specified with monitor_type 'm_of_n'."
)
if self.want.monitors != self.have.monitors:
return dict(
monitors=self.want.monitors
)
elif self.want.monitor_type == 'and_list':
if self.want.quorum is not None and self.want.quorum > 0:
raise F5ModuleError(
"Quorum values have no effect when used with 'and_list'."
)
if self.want.monitors != self.have.monitors:
return dict(
monitors=self.want.monitors
)
elif self.want.monitor_type == 'single':
if len(self.want.monitors_list) > 1:
raise F5ModuleError(
@ -598,8 +636,18 @@ class Difference(object):
# Remember that 'single' is nothing more than a fancy way of saying
# "and_list plus some extra checks"
self.want.update(dict(monitor_type='and_list'))
if self.want.monitor_type != self.have.monitor_type:
return self.want.monitor_type
if self.want.monitors != self.have.monitors:
return dict(
monitors=self.want.monitors
)
@property
def monitor_type(self):
return self._monitors_and_quorum()
@property
def quorum(self):
return self._monitors_and_quorum()
@property
def monitors(self):
@ -734,10 +782,14 @@ class ModuleManager(object):
if self.want.monitor_type is None:
self.want.update(dict(monitor_type='and_list'))
if self.want.monitor_type == 'm_of_n' and self.want.quorum is None:
if self.want.monitor_type == 'm_of_n' and (self.want.quorum is None or self.want.quorum < 1):
raise F5ModuleError(
"Quorum value must be specified with monitor_type 'm_of_n'."
)
elif self.want.monitor_type == 'and_list' and self.want.quorum is not None and self.want.quorum > 0:
raise F5ModuleError(
"Quorum values have no effect when used with 'and_list'."
)
elif self.want.monitor_type == 'single' and len(self.want.monitors_list) > 1:
raise F5ModuleError(
"When using a 'monitor_type' of 'single', only one monitor may be provided"

@ -97,6 +97,17 @@ options:
- yes
- no
version_added: 2.1
priority_group:
description:
- Specifies a number representing the priority group for the pool member.
- When adding a new member, the default is 0, meaning that the member has no priority.
- To specify a priority, you must activate priority group usage when you
create a new pool or when adding or removing pool members. When activated,
the system load balances traffic according to the priority group number
assigned to the pool member.
- The higher the number, the higher the priority, so a member with a priority
of 3 has higher priority than a member with a priority of 1.
version_added: 2.5
extends_documentation_fragment: f5
'''

@ -35,6 +35,15 @@ options:
provide no local IP, specify the value C(none). When creating a
remote syslog, if this parameter is not specified, the default value
C(none) is used.
state:
description:
- When C(present), guarantees that the remote syslog exists with the provided
attributes.
- When C(absent), removes the remote syslog from the system.
default: present
choices:
- absent
- present
notes:
- Requires the netaddr Python package on the host. This is as easy as pip
install netaddr.

@ -49,6 +49,11 @@ options:
region:
description:
- Region name of the country to use.
addresses:
description:
- Individual addresses that you want to add to the list. These addresses differ
from ranges, and lists of lists such as what can be used in C(address_ranges)
and C(address_lists) respectively.
address_ranges:
description:
- A list of address ranges where the range starts with a port number, is followed

@ -41,9 +41,9 @@ options:
is required.
state:
description:
- The state of the variable on the system. When C(present), guarantees
that the Self-IP exists with the provided attributes. When C(absent),
removes the Self-IP from the system.
- When C(present), guarantees that the Self-IP exists with the provided
attributes.
- When C(absent), removes the Self-IP from the system.
default: present
choices:
- absent

@ -39,7 +39,7 @@ options:
partition:
description:
- Device partition to manage resources on.
default: 'Common'
default: Common
version_added: 2.5
notes:
- Requires the netaddr Python package on the host. This is as easy as

@ -152,7 +152,7 @@ options:
- Device partition to manage resources on.
default: Common
version_added: 2.5
metdata:
metadata:
description:
- Arbitrary key/value pairs that you can attach to a pool. This is useful in
situations where you might want to annotate a virtual to me managed by Ansible.

@ -91,7 +91,12 @@ options:
- When creating a new VLAN, if this parameter is not specified, the default
of (no) is used.
version_added: 2.5
choices: [yes, no]
type: bool
partition:
description:
- Device partition to manage resources on.
default: Common
version_added: 2.5
notes:
- Requires BIG-IP versions >= 12.0.0
extends_documentation_fragment: f5

@ -377,129 +377,6 @@ lib/ansible/modules/network/enos/enos_command.py E323
lib/ansible/modules/network/enos/enos_config.py E323
lib/ansible/modules/network/enos/enos_facts.py E323
lib/ansible/modules/network/eos/eos_linkagg.py E322
lib/ansible/modules/network/f5/bigip_asm_policy.py E322
lib/ansible/modules/network/f5/bigip_asm_policy.py E323
lib/ansible/modules/network/f5/bigip_command.py E322
lib/ansible/modules/network/f5/bigip_command.py E323
lib/ansible/modules/network/f5/bigip_config.py E322
lib/ansible/modules/network/f5/bigip_config.py E323
lib/ansible/modules/network/f5/bigip_configsync_action.py E322
lib/ansible/modules/network/f5/bigip_configsync_action.py E323
lib/ansible/modules/network/f5/bigip_device_connectivity.py E322
lib/ansible/modules/network/f5/bigip_device_connectivity.py E323
lib/ansible/modules/network/f5/bigip_device_dns.py E322
lib/ansible/modules/network/f5/bigip_device_dns.py E323
lib/ansible/modules/network/f5/bigip_device_group.py E322
lib/ansible/modules/network/f5/bigip_device_group.py E323
lib/ansible/modules/network/f5/bigip_device_httpd.py E322
lib/ansible/modules/network/f5/bigip_device_httpd.py E323
lib/ansible/modules/network/f5/bigip_device_ntp.py E322
lib/ansible/modules/network/f5/bigip_device_ntp.py E323
lib/ansible/modules/network/f5/bigip_device_sshd.py E322
lib/ansible/modules/network/f5/bigip_device_sshd.py E323
lib/ansible/modules/network/f5/bigip_device_trust.py E322
lib/ansible/modules/network/f5/bigip_device_trust.py E323
lib/ansible/modules/network/f5/bigip_facts.py E322
lib/ansible/modules/network/f5/bigip_facts.py E323
lib/ansible/modules/network/f5/bigip_gtm_datacenter.py E322
lib/ansible/modules/network/f5/bigip_gtm_datacenter.py E323
lib/ansible/modules/network/f5/bigip_gtm_facts.py E322
lib/ansible/modules/network/f5/bigip_gtm_facts.py E323
lib/ansible/modules/network/f5/bigip_gtm_pool.py E322
lib/ansible/modules/network/f5/bigip_gtm_pool.py E323
lib/ansible/modules/network/f5/bigip_gtm_server.py E322
lib/ansible/modules/network/f5/bigip_gtm_server.py E323
lib/ansible/modules/network/f5/bigip_gtm_virtual_server.py E322
lib/ansible/modules/network/f5/bigip_gtm_wide_ip.py E322
lib/ansible/modules/network/f5/bigip_gtm_wide_ip.py E323
lib/ansible/modules/network/f5/bigip_hostname.py E322
lib/ansible/modules/network/f5/bigip_hostname.py E323
lib/ansible/modules/network/f5/bigip_iapp_service.py E322
lib/ansible/modules/network/f5/bigip_iapp_service.py E323
lib/ansible/modules/network/f5/bigip_iapp_template.py E322
lib/ansible/modules/network/f5/bigip_iapp_template.py E323
lib/ansible/modules/network/f5/bigip_iapplx_package.py E322
lib/ansible/modules/network/f5/bigip_iapplx_package.py E323
lib/ansible/modules/network/f5/bigip_irule.py E322
lib/ansible/modules/network/f5/bigip_irule.py E323
lib/ansible/modules/network/f5/bigip_monitor_http.py E322
lib/ansible/modules/network/f5/bigip_monitor_http.py E323
lib/ansible/modules/network/f5/bigip_monitor_https.py E322
lib/ansible/modules/network/f5/bigip_monitor_https.py E323
lib/ansible/modules/network/f5/bigip_monitor_snmp_dca.py E322
lib/ansible/modules/network/f5/bigip_monitor_snmp_dca.py E323
lib/ansible/modules/network/f5/bigip_monitor_tcp.py E322
lib/ansible/modules/network/f5/bigip_monitor_tcp.py E323
lib/ansible/modules/network/f5/bigip_monitor_tcp_echo.py E322
lib/ansible/modules/network/f5/bigip_monitor_tcp_echo.py E323
lib/ansible/modules/network/f5/bigip_monitor_tcp_half_open.py E322
lib/ansible/modules/network/f5/bigip_monitor_tcp_half_open.py E323
lib/ansible/modules/network/f5/bigip_monitor_udp.py E322
lib/ansible/modules/network/f5/bigip_monitor_udp.py E323
lib/ansible/modules/network/f5/bigip_node.py E322
lib/ansible/modules/network/f5/bigip_node.py E323
lib/ansible/modules/network/f5/bigip_partition.py E322
lib/ansible/modules/network/f5/bigip_partition.py E323
lib/ansible/modules/network/f5/bigip_policy.py E322
lib/ansible/modules/network/f5/bigip_policy.py E323
lib/ansible/modules/network/f5/bigip_policy_rule.py E322
lib/ansible/modules/network/f5/bigip_policy_rule.py E323
lib/ansible/modules/network/f5/bigip_pool.py E322
lib/ansible/modules/network/f5/bigip_pool.py E323
lib/ansible/modules/network/f5/bigip_pool_member.py E322
lib/ansible/modules/network/f5/bigip_pool_member.py E323
lib/ansible/modules/network/f5/bigip_profile_client_ssl.py E322
lib/ansible/modules/network/f5/bigip_profile_client_ssl.py E323
lib/ansible/modules/network/f5/bigip_provision.py E322
lib/ansible/modules/network/f5/bigip_provision.py E323
lib/ansible/modules/network/f5/bigip_qkview.py E322
lib/ansible/modules/network/f5/bigip_qkview.py E323
lib/ansible/modules/network/f5/bigip_remote_syslog.py E322
lib/ansible/modules/network/f5/bigip_remote_syslog.py E323
lib/ansible/modules/network/f5/bigip_security_address_list.py E322
lib/ansible/modules/network/f5/bigip_security_address_list.py E323
lib/ansible/modules/network/f5/bigip_security_port_list.py E322
lib/ansible/modules/network/f5/bigip_security_port_list.py E323
lib/ansible/modules/network/f5/bigip_selfip.py E322
lib/ansible/modules/network/f5/bigip_selfip.py E323
lib/ansible/modules/network/f5/bigip_snat_pool.py E322
lib/ansible/modules/network/f5/bigip_snat_pool.py E323
lib/ansible/modules/network/f5/bigip_snmp.py E322
lib/ansible/modules/network/f5/bigip_snmp.py E323
lib/ansible/modules/network/f5/bigip_snmp_trap.py E322
lib/ansible/modules/network/f5/bigip_snmp_trap.py E323
lib/ansible/modules/network/f5/bigip_software_update.py E322
lib/ansible/modules/network/f5/bigip_software_update.py E323
lib/ansible/modules/network/f5/bigip_ssl_certificate.py E322
lib/ansible/modules/network/f5/bigip_ssl_certificate.py E323
lib/ansible/modules/network/f5/bigip_ssl_key.py E322
lib/ansible/modules/network/f5/bigip_ssl_key.py E323
lib/ansible/modules/network/f5/bigip_static_route.py E322
lib/ansible/modules/network/f5/bigip_static_route.py E323
lib/ansible/modules/network/f5/bigip_sys_db.py E322
lib/ansible/modules/network/f5/bigip_sys_db.py E323
lib/ansible/modules/network/f5/bigip_sys_global.py E322
lib/ansible/modules/network/f5/bigip_sys_global.py E323
lib/ansible/modules/network/f5/bigip_traffic_group.py E322
lib/ansible/modules/network/f5/bigip_traffic_group.py E323
lib/ansible/modules/network/f5/bigip_ucs.py E322
lib/ansible/modules/network/f5/bigip_ucs.py E323
lib/ansible/modules/network/f5/bigip_user.py E322
lib/ansible/modules/network/f5/bigip_user.py E323
lib/ansible/modules/network/f5/bigip_vcmp_guest.py E322
lib/ansible/modules/network/f5/bigip_vcmp_guest.py E323
lib/ansible/modules/network/f5/bigip_virtual_address.py E322
lib/ansible/modules/network/f5/bigip_virtual_address.py E323
lib/ansible/modules/network/f5/bigip_virtual_server.py E322
lib/ansible/modules/network/f5/bigip_virtual_server.py E323
lib/ansible/modules/network/f5/bigip_vlan.py E322
lib/ansible/modules/network/f5/bigip_vlan.py E323
lib/ansible/modules/network/f5/bigip_wait.py E322
lib/ansible/modules/network/f5/bigip_wait.py E323
lib/ansible/modules/network/f5/bigiq_regkey_license.py E322
lib/ansible/modules/network/f5/bigiq_regkey_license.py E323
lib/ansible/modules/network/f5/bigiq_regkey_pool.py E322
lib/ansible/modules/network/f5/bigiq_regkey_pool.py E323
lib/ansible/modules/network/illumos/dladm_linkprop.py E317
lib/ansible/modules/network/illumos/ipadm_addrprop.py E317
lib/ansible/modules/network/illumos/ipadm_ifprop.py E317

@ -135,7 +135,7 @@ class TestManager(unittest.TestCase):
# Configure the parameters that would be returned by querying the
# remote device
current = Parameters(
dict(
params=dict(
agent_status_traps='disabled'
)
)

Loading…
Cancel
Save