mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Remove Deprecated Template network modules (#27076)
* removed deprecated networking template modules * update changelog * update changelog
This commit is contained in:
parent
0fb64214a4
commit
81151ef02c
86 changed files with 8 additions and 3420 deletions
|
@ -50,6 +50,14 @@ Ansible Changes By Release
|
||||||
#### Deprecated Modules:
|
#### Deprecated Modules:
|
||||||
* ec2_facts (removed in 2.7), replaced by ec2_metadata_facts
|
* ec2_facts (removed in 2.7), replaced by ec2_metadata_facts
|
||||||
|
|
||||||
|
#### Removed Deprecated Modules:
|
||||||
|
* eos_template (use eos_config instead)
|
||||||
|
* ios_template (use ios_config instead)
|
||||||
|
* iosxr_template (use iosxr_config instead)
|
||||||
|
* junos_template (use junos_config instead)
|
||||||
|
* nxos_template (use nxos_config instead)
|
||||||
|
* ops_template (use ops_template instead)
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
* removed previously deprecated config option `hostfile` and env var `ANSIBLE_HOSTS`
|
* removed previously deprecated config option `hostfile` and env var `ANSIBLE_HOSTS`
|
||||||
* removed unused and deprecated config option `pattern`
|
* removed unused and deprecated config option `pattern`
|
||||||
|
|
|
@ -1,232 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
ANSIBLE_METADATA = {'metadata_version': '1.0',
|
|
||||||
'status': ['deprecated'],
|
|
||||||
'supported_by': 'community'}
|
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = """
|
|
||||||
---
|
|
||||||
module: eos_template
|
|
||||||
version_added: "2.1"
|
|
||||||
author: "Peter Sprygada (@privateip)"
|
|
||||||
short_description: Manage Arista EOS device configurations
|
|
||||||
description:
|
|
||||||
- Manages network device configurations over SSH or eos_local. This module
|
|
||||||
allows implementers to work with the device running-config. It
|
|
||||||
provides a way to push a set of commands onto a network device
|
|
||||||
by evaluating the current running-config and only pushing configuration
|
|
||||||
commands that are not already configured. The config source can
|
|
||||||
be a set of commands or a template.
|
|
||||||
extends_documentation_fragment: eos
|
|
||||||
deprecated: Deprecated in 2.2. Use M(eos_config) instead
|
|
||||||
options:
|
|
||||||
src:
|
|
||||||
description:
|
|
||||||
- The path to the config source. The source can be either a
|
|
||||||
file with config or a template that will be merged during
|
|
||||||
runtime. By default the task will search for the source
|
|
||||||
file in role or playbook root folder in templates directory.
|
|
||||||
required: true
|
|
||||||
force:
|
|
||||||
description:
|
|
||||||
- The force argument instructs the module to not consider the
|
|
||||||
current devices running-config. When set to true, this will
|
|
||||||
cause the module to push the contents of I(src) into the device
|
|
||||||
without first checking if already configured.
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
choices: ['yes', 'no']
|
|
||||||
include_defaults:
|
|
||||||
description:
|
|
||||||
- By default when the M(eos_template) connects to the remote
|
|
||||||
device to retrieve the configuration it will issue the C(show
|
|
||||||
running-config) command. If this option is set to True then
|
|
||||||
the issued command will be C(show running-config all).
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
choices: ['yes', 'no']
|
|
||||||
backup:
|
|
||||||
description:
|
|
||||||
- When this argument is configured true, the module will backup
|
|
||||||
the running-config from the node prior to making any changes.
|
|
||||||
The backup file will be written to backup_{{ hostname }} in
|
|
||||||
the root of the playbook directory.
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
choices: ['yes', 'no']
|
|
||||||
replace:
|
|
||||||
description:
|
|
||||||
- This argument will cause the provided configuration to be replaced
|
|
||||||
on the destination node. The use of the replace argument will
|
|
||||||
always cause the task to set changed to true and will implies
|
|
||||||
C(force=true). This argument is only valid with C(transport=eos_local).
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
choices: ['yes', 'no']
|
|
||||||
config:
|
|
||||||
description:
|
|
||||||
- The module, by default, will connect to the remote device and
|
|
||||||
retrieve the current running-config to use as a base for comparing
|
|
||||||
against the contents of source. There are times when it is not
|
|
||||||
desirable to have the task get the current running-config for
|
|
||||||
every task in a playbook. The I(config) argument allows the
|
|
||||||
implementer to pass in the configuration to use as the base
|
|
||||||
config for comparison.
|
|
||||||
required: false
|
|
||||||
default: null
|
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = """
|
|
||||||
- name: Push a configuration onto the device
|
|
||||||
eos_template:
|
|
||||||
src: config.j2
|
|
||||||
|
|
||||||
- name: Forceable push a configuration onto the device
|
|
||||||
eos_template:
|
|
||||||
src: config.j2
|
|
||||||
force: yes
|
|
||||||
|
|
||||||
- name: Provide the base configuration for comparison
|
|
||||||
eos_template:
|
|
||||||
src: candidate_config.txt
|
|
||||||
config: current_config.txt
|
|
||||||
"""
|
|
||||||
|
|
||||||
RETURN = """
|
|
||||||
updates:
|
|
||||||
description: The set of commands that will be pushed to the remote device
|
|
||||||
returned: always
|
|
||||||
type: list
|
|
||||||
sample: ['...', '...']
|
|
||||||
|
|
||||||
responses:
|
|
||||||
description: The set of responses from issuing the commands on the device
|
|
||||||
returned: when not check_mode
|
|
||||||
type: list
|
|
||||||
sample: ['...', '...']
|
|
||||||
"""
|
|
||||||
import re
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
from ansible.module_utils.eos import load_config, get_config
|
|
||||||
from ansible.module_utils.eos import eos_argument_spec
|
|
||||||
from ansible.module_utils.eos import check_args as eos_check_args
|
|
||||||
from ansible.module_utils.netcfg import NetworkConfig, dumps
|
|
||||||
|
|
||||||
def check_args(module, warnings):
|
|
||||||
eos_check_args(module, warnings)
|
|
||||||
|
|
||||||
transport = module.params['transport']
|
|
||||||
provider_transport = (module.params['provider'] or {}).get('transport')
|
|
||||||
|
|
||||||
if module.params['replace'] and 'eapi' in (transport, provider_transport):
|
|
||||||
module.fail_json(msg='config replace is only supported over cli')
|
|
||||||
|
|
||||||
def get_current_config(module):
|
|
||||||
config = module.params.get('config')
|
|
||||||
if not config and not module.params['force']:
|
|
||||||
flags = []
|
|
||||||
if module.params['include_defaults']:
|
|
||||||
flags.append('all')
|
|
||||||
config = get_config(module, flags)
|
|
||||||
return config
|
|
||||||
|
|
||||||
def filter_exit(commands):
|
|
||||||
# Filter out configuration mode commands followed immediately by an
|
|
||||||
# exit command indented by one level only, e.g.
|
|
||||||
# - route-map map01 permit 10
|
|
||||||
# - exit
|
|
||||||
#
|
|
||||||
# Build a temporary list as we filter, then copy the temp list
|
|
||||||
# back onto the commands list.
|
|
||||||
temp = []
|
|
||||||
ind_prev = 999
|
|
||||||
count = 0
|
|
||||||
for c in commands:
|
|
||||||
ind_this = c.count(' ')
|
|
||||||
if re.search(r"^\s*exit$", c) and ind_this == ind_prev + 1:
|
|
||||||
temp.pop()
|
|
||||||
count -= 1
|
|
||||||
if count != 0:
|
|
||||||
ind_prev = temp[-1].count(' ')
|
|
||||||
continue
|
|
||||||
temp.append(c)
|
|
||||||
ind_prev = ind_this
|
|
||||||
count += 1
|
|
||||||
return temp
|
|
||||||
|
|
||||||
def main():
|
|
||||||
""" main entry point for module execution
|
|
||||||
"""
|
|
||||||
|
|
||||||
argument_spec = dict(
|
|
||||||
src=dict(required=True),
|
|
||||||
force=dict(default=False, type='bool'),
|
|
||||||
include_defaults=dict(default=False, type='bool'),
|
|
||||||
backup=dict(default=False, type='bool'),
|
|
||||||
replace=dict(default=False, type='bool'),
|
|
||||||
config=dict()
|
|
||||||
)
|
|
||||||
|
|
||||||
argument_spec.update(eos_argument_spec)
|
|
||||||
|
|
||||||
mutually_exclusive = [('config', 'backup'), ('config', 'force')]
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
|
||||||
mutually_exclusive=mutually_exclusive,
|
|
||||||
supports_check_mode=True)
|
|
||||||
|
|
||||||
warnings = list()
|
|
||||||
check_args(module, warnings)
|
|
||||||
|
|
||||||
result = {'changed': False}
|
|
||||||
if warnings:
|
|
||||||
result['warnings'] = warnings
|
|
||||||
|
|
||||||
src = module.params['src']
|
|
||||||
candidate = NetworkConfig(contents=src, indent=3)
|
|
||||||
|
|
||||||
if module.params['backup']:
|
|
||||||
result['__backup__'] = get_config(module)
|
|
||||||
|
|
||||||
if not module.params['force']:
|
|
||||||
contents = get_current_config(module)
|
|
||||||
configobj = NetworkConfig(contents=contents, indent=3)
|
|
||||||
commands = candidate.difference(configobj)
|
|
||||||
commands = dumps(commands, 'commands').split('\n')
|
|
||||||
commands = [str(c).strip() for c in commands if c]
|
|
||||||
else:
|
|
||||||
commands = [c.strip() for c in str(candidate).split('\n')]
|
|
||||||
|
|
||||||
#commands = str(candidate).split('\n')
|
|
||||||
|
|
||||||
if commands:
|
|
||||||
commands = filter_exit(commands)
|
|
||||||
commit = not module.check_mode
|
|
||||||
replace = module.params['replace'] or False
|
|
||||||
load_config(module, commands, commit=commit, replace=replace)
|
|
||||||
result['changed'] = True
|
|
||||||
|
|
||||||
result['commands'] = commands
|
|
||||||
result['updates'] = commands
|
|
||||||
|
|
||||||
module.exit_json(**result)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,175 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
ANSIBLE_METADATA = {'metadata_version': '1.0',
|
|
||||||
'status': ['deprecated'],
|
|
||||||
'supported_by': 'community'}
|
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = """
|
|
||||||
---
|
|
||||||
module: ios_template
|
|
||||||
version_added: "2.1"
|
|
||||||
author: "Peter Sprygada (@privateip)"
|
|
||||||
short_description: Manage Cisco IOS device configurations over SSH
|
|
||||||
description:
|
|
||||||
- Manages Cisco IOS network device configurations over SSH. This module
|
|
||||||
allows implementers to work with the device running-config. It
|
|
||||||
provides a way to push a set of commands onto a network device
|
|
||||||
by evaluating the current running-config and only pushing configuration
|
|
||||||
commands that are not already configured. The config source can
|
|
||||||
be a set of commands or a template.
|
|
||||||
deprecated: Deprecated in 2.2. Use M(ios_config) instead.
|
|
||||||
extends_documentation_fragment: ios
|
|
||||||
options:
|
|
||||||
src:
|
|
||||||
description:
|
|
||||||
- The path to the config source. The source can be either a
|
|
||||||
file with config or a template that will be merged during
|
|
||||||
runtime. By default the task will first search for the source
|
|
||||||
file in role or playbook root folder in templates unless a full
|
|
||||||
path to the file is given.
|
|
||||||
required: true
|
|
||||||
force:
|
|
||||||
description:
|
|
||||||
- The force argument instructs the module not to consider the
|
|
||||||
current device running-config. When set to true, this will
|
|
||||||
cause the module to push the contents of I(src) into the device
|
|
||||||
without first checking if already configured.
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
choices: [ "true", "false" ]
|
|
||||||
include_defaults:
|
|
||||||
description:
|
|
||||||
- The module, by default, will collect the current device
|
|
||||||
running-config to use as a base for comparison to the commands
|
|
||||||
in I(src). Setting this value to true will cause the command
|
|
||||||
issued to add any necessary flags to collect all defaults as
|
|
||||||
well as the device configuration. If the destination device
|
|
||||||
does not support such a flag, this argument is silently ignored.
|
|
||||||
required: true
|
|
||||||
choices: [ "true", "false" ]
|
|
||||||
backup:
|
|
||||||
description:
|
|
||||||
- When this argument is configured true, the module will backup
|
|
||||||
the running-config from the node prior to making any changes.
|
|
||||||
The backup file will be written to backup_{{ hostname }} in
|
|
||||||
the root of the playbook directory.
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
choices: [ "true", "false" ]
|
|
||||||
config:
|
|
||||||
description:
|
|
||||||
- The module, by default, will connect to the remote device and
|
|
||||||
retrieve the current running-config to use as a base for comparing
|
|
||||||
against the contents of source. There are times when it is not
|
|
||||||
desirable to have the task get the current running-config for
|
|
||||||
every task. The I(config) argument allows the implementer to
|
|
||||||
pass in the configuration to use as the base config for
|
|
||||||
comparison.
|
|
||||||
required: false
|
|
||||||
default: null
|
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = """
|
|
||||||
- name: push a configuration onto the device
|
|
||||||
ios_template:
|
|
||||||
src: config.j2
|
|
||||||
|
|
||||||
- name: forceable push a configuration onto the device
|
|
||||||
ios_template:
|
|
||||||
src: config.j2
|
|
||||||
force: yes
|
|
||||||
|
|
||||||
- name: provide the base configuration for comparison
|
|
||||||
ios_template:
|
|
||||||
src: candidate_config.txt
|
|
||||||
config: current_config.txt
|
|
||||||
"""
|
|
||||||
|
|
||||||
RETURN = """
|
|
||||||
updates:
|
|
||||||
description: The set of commands that will be pushed to the remote device
|
|
||||||
returned: always
|
|
||||||
type: list
|
|
||||||
sample: ['...', '...']
|
|
||||||
"""
|
|
||||||
from ansible.module_utils.ios import load_config, get_config
|
|
||||||
from ansible.module_utils.ios import ios_argument_spec, check_args
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
from ansible.module_utils.netcli import Conditional
|
|
||||||
from ansible.module_utils.netcfg import NetworkConfig, dumps
|
|
||||||
|
|
||||||
def get_current_config(module):
|
|
||||||
if module.params['config']:
|
|
||||||
return module.params['config']
|
|
||||||
if module.params['include_defaults']:
|
|
||||||
flags = ['all']
|
|
||||||
else:
|
|
||||||
flags = []
|
|
||||||
return get_config(module=module, flags=flags)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
""" main entry point for module execution
|
|
||||||
"""
|
|
||||||
argument_spec = dict(
|
|
||||||
src=dict(),
|
|
||||||
force=dict(default=False, type='bool'),
|
|
||||||
include_defaults=dict(default=True, type='bool'),
|
|
||||||
backup=dict(default=False, type='bool'),
|
|
||||||
config=dict(),
|
|
||||||
)
|
|
||||||
|
|
||||||
argument_spec.update(ios_argument_spec)
|
|
||||||
|
|
||||||
mutually_exclusive = [('config', 'backup'), ('config', 'force')]
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
|
||||||
mutually_exclusive=mutually_exclusive,
|
|
||||||
supports_check_mode=True)
|
|
||||||
|
|
||||||
candidate = NetworkConfig(contents=module.params['src'], indent=1)
|
|
||||||
|
|
||||||
result = {'changed': False}
|
|
||||||
warnings = list()
|
|
||||||
check_args(module, warnings)
|
|
||||||
result['warnings'] = warnings
|
|
||||||
|
|
||||||
if module.params['backup']:
|
|
||||||
result['__backup__'] = get_config(module=module)
|
|
||||||
|
|
||||||
if not module.params['force']:
|
|
||||||
contents = get_current_config(module)
|
|
||||||
configobj = NetworkConfig(contents=contents, indent=1)
|
|
||||||
commands = candidate.difference(configobj)
|
|
||||||
commands = dumps(commands, 'commands').split('\n')
|
|
||||||
commands = [str(c).strip() for c in commands if c]
|
|
||||||
else:
|
|
||||||
commands = [c.strip() for c in str(candidate).split('\n')]
|
|
||||||
|
|
||||||
if commands:
|
|
||||||
if not module.check_mode:
|
|
||||||
load_config(module, commands)
|
|
||||||
result['changed'] = True
|
|
||||||
|
|
||||||
result['updates'] = commands
|
|
||||||
result['commands'] = commands
|
|
||||||
|
|
||||||
module.exit_json(**result)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,158 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
ANSIBLE_METADATA = {'metadata_version': '1.0',
|
|
||||||
'status': ['deprecated'],
|
|
||||||
'supported_by': 'community'}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = """
|
|
||||||
---
|
|
||||||
module: iosxr_template
|
|
||||||
version_added: "2.1"
|
|
||||||
author: "Ricardo Carrillo Cruz (@rcarrillocruz)"
|
|
||||||
short_description: Manage Cisco IOS XR device configurations over SSH
|
|
||||||
description:
|
|
||||||
- Manages network device configurations over SSH. This module
|
|
||||||
allows implementers to work with the device running-config. It
|
|
||||||
provides a way to push a set of commands onto a network device
|
|
||||||
by evaluating the current running-config and only pushing configuration
|
|
||||||
commands that are not already configured. The config source can
|
|
||||||
be a set of commands or a template.
|
|
||||||
deprecated: Deprecated in 2.2. Use M(iosxr_config) instead.
|
|
||||||
extends_documentation_fragment: iosxr
|
|
||||||
options:
|
|
||||||
src:
|
|
||||||
description:
|
|
||||||
- The path to the config source. The source can be either a
|
|
||||||
file with config or a template that will be merged during
|
|
||||||
runtime. By default the task will first search for the source
|
|
||||||
file in role or playbook root folder in templates unless a full
|
|
||||||
path to the file is given.
|
|
||||||
required: false
|
|
||||||
default: null
|
|
||||||
force:
|
|
||||||
description:
|
|
||||||
- The force argument instructs the module not to consider the
|
|
||||||
current device running-config. When set to true, this will
|
|
||||||
cause the module to push the contents of I(src) into the device
|
|
||||||
without first checking if already configured.
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
choices: [ "true", "false" ]
|
|
||||||
backup:
|
|
||||||
description:
|
|
||||||
- When this argument is configured true, the module will backup
|
|
||||||
the running-config from the node prior to making any changes.
|
|
||||||
The backup file will be written to backup_{{ hostname }} in
|
|
||||||
the root of the playbook directory.
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
choices: [ "true", "false" ]
|
|
||||||
config:
|
|
||||||
description:
|
|
||||||
- The module, by default, will connect to the remote device and
|
|
||||||
retrieve the current running-config to use as a base for comparing
|
|
||||||
against the contents of source. There are times when it is not
|
|
||||||
desirable to have the task get the current running-config for
|
|
||||||
every task. The I(config) argument allows the implementer to
|
|
||||||
pass in the configuration to use as the base config for
|
|
||||||
comparison.
|
|
||||||
required: false
|
|
||||||
default: null
|
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = """
|
|
||||||
|
|
||||||
- name: push a configuration onto the device
|
|
||||||
iosxr_template:
|
|
||||||
src: config.j2
|
|
||||||
|
|
||||||
- name: forceable push a configuration onto the device
|
|
||||||
iosxr_template:
|
|
||||||
src: config.j2
|
|
||||||
force: yes
|
|
||||||
|
|
||||||
- name: provide the base configuration for comparison
|
|
||||||
iosxr_template:
|
|
||||||
src: candidate_config.txt
|
|
||||||
config: current_config.txt
|
|
||||||
"""
|
|
||||||
|
|
||||||
RETURN = """
|
|
||||||
updates:
|
|
||||||
description: The set of commands that will be pushed to the remote device
|
|
||||||
returned: always
|
|
||||||
type: list
|
|
||||||
sample: ['...', '...']
|
|
||||||
"""
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
from ansible.module_utils.netcfg import NetworkConfig, dumps
|
|
||||||
from ansible.module_utils.iosxr import get_config, load_config
|
|
||||||
from ansible.module_utils.iosxr import iosxr_argument_spec, check_args
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
""" main entry point for module execution
|
|
||||||
"""
|
|
||||||
|
|
||||||
argument_spec = dict(
|
|
||||||
src=dict(),
|
|
||||||
force=dict(default=False, type='bool'),
|
|
||||||
backup=dict(default=False, type='bool'),
|
|
||||||
config=dict(),
|
|
||||||
)
|
|
||||||
|
|
||||||
argument_spec.update(iosxr_argument_spec)
|
|
||||||
|
|
||||||
mutually_exclusive = [('config', 'backup'), ('config', 'force')]
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
|
||||||
mutually_exclusive=mutually_exclusive,
|
|
||||||
supports_check_mode=True)
|
|
||||||
|
|
||||||
warnings = list()
|
|
||||||
check_args(module, warnings)
|
|
||||||
|
|
||||||
result = dict(changed=False, warnings=warnings)
|
|
||||||
|
|
||||||
candidate = NetworkConfig(contents=module.params['src'], indent=1)
|
|
||||||
|
|
||||||
if module.params['backup']:
|
|
||||||
result['__backup__'] = get_config(module)
|
|
||||||
|
|
||||||
if not module.params['force']:
|
|
||||||
contents = get_config(module)
|
|
||||||
configobj = NetworkConfig(contents=contents, indent=1)
|
|
||||||
commands = candidate.difference(configobj)
|
|
||||||
commands = dumps(commands, 'commands').split('\n')
|
|
||||||
commands = [str(c).strip() for c in commands if c]
|
|
||||||
else:
|
|
||||||
commands = [c.strip() for c in str(candidate).split('\n')]
|
|
||||||
|
|
||||||
if commands:
|
|
||||||
load_config(module, commands, result['warnings'], not module.check_mode)
|
|
||||||
result['changed'] = not module.check_mode
|
|
||||||
|
|
||||||
result['updates'] = commands
|
|
||||||
result['commands'] = commands
|
|
||||||
module.exit_json(**result)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,173 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
|
|
||||||
ANSIBLE_METADATA = {'metadata_version': '1.0',
|
|
||||||
'status': ['deprecated'],
|
|
||||||
'supported_by': 'community'}
|
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = """
|
|
||||||
---
|
|
||||||
module: junos_template
|
|
||||||
version_added: "2.1"
|
|
||||||
author: "Peter Sprygada (@privateip)"
|
|
||||||
short_description: Manage configuration on remote devices running Juniper JUNOS
|
|
||||||
description:
|
|
||||||
- This module will load a candidate configuration
|
|
||||||
from a template file onto a remote device running Junos. The
|
|
||||||
module will return the differences in configuration if the diff
|
|
||||||
option is specified on the Ansible command line
|
|
||||||
deprecated: Deprecated in 2.2. Use M(junos_config) instead.
|
|
||||||
extends_documentation_fragment: junos
|
|
||||||
options:
|
|
||||||
src:
|
|
||||||
description:
|
|
||||||
- The path to the config source. The source can be either a
|
|
||||||
file with config or a template that will be merged during
|
|
||||||
runtime. By default the task will search for the source
|
|
||||||
file in role or playbook root folder in templates directory.
|
|
||||||
required: true
|
|
||||||
default: null
|
|
||||||
backup:
|
|
||||||
description:
|
|
||||||
- When this argument is configured true, the module will backup
|
|
||||||
the configuration from the node prior to making any changes.
|
|
||||||
The backup file will be written to backup_{{ hostname }} in
|
|
||||||
the root of the playbook directory.
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
choices: ["true", "false"]
|
|
||||||
confirm:
|
|
||||||
description:
|
|
||||||
- The C(confirm) argument will configure a time out value for
|
|
||||||
the commit to be confirmed before it is automatically
|
|
||||||
rolled back. If the C(confirm) argument is set to False, this
|
|
||||||
argument is silently ignored. If the value for this argument
|
|
||||||
is set to 0, the commit is confirmed immediately.
|
|
||||||
required: false
|
|
||||||
default: 0
|
|
||||||
comment:
|
|
||||||
description:
|
|
||||||
- The C(comment) argument specifies a text string to be used
|
|
||||||
when committing the configuration. If the C(confirm) argument
|
|
||||||
is set to False, this argument is silently ignored.
|
|
||||||
required: false
|
|
||||||
default: configured by junos_template
|
|
||||||
action:
|
|
||||||
description:
|
|
||||||
- The C(action) argument specifies how the module will apply changes.
|
|
||||||
required: false
|
|
||||||
default: merge
|
|
||||||
choices: ['merge', 'overwrite', 'replace']
|
|
||||||
version_added: "2.2"
|
|
||||||
config_format:
|
|
||||||
description:
|
|
||||||
- The C(format) argument specifies the format of the configuration
|
|
||||||
template specified in C(src). If the format argument is not
|
|
||||||
specified, the module will attempt to infer the configuration
|
|
||||||
format based of file extension. Files that end in I(xml) will set
|
|
||||||
the format to xml. Files that end in I(set) will set the format
|
|
||||||
to set and all other files will default the format to text.
|
|
||||||
required: false
|
|
||||||
default: null
|
|
||||||
choices: ['text', 'xml', 'set']
|
|
||||||
requirements:
|
|
||||||
- ncclient (>=v0.5.2)
|
|
||||||
notes:
|
|
||||||
- This module requires the netconf system service be enabled on
|
|
||||||
the remote device being managed
|
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = """
|
|
||||||
- junos_template:
|
|
||||||
src: config.j2
|
|
||||||
comment: update system config
|
|
||||||
|
|
||||||
- name: replace config hierarchy
|
|
||||||
junos_template:
|
|
||||||
src: config.j2
|
|
||||||
action: replace
|
|
||||||
|
|
||||||
- name: overwrite the config
|
|
||||||
junos_template:
|
|
||||||
src: config.j2
|
|
||||||
action: overwrite
|
|
||||||
"""
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
from ansible.module_utils.junos import check_args, junos_argument_spec
|
|
||||||
from ansible.module_utils.junos import get_configuration, load_config
|
|
||||||
from ansible.module_utils.junos import commit_configuration, discard_changes, locked_config
|
|
||||||
|
|
||||||
USE_PERSISTENT_CONNECTION = True
|
|
||||||
DEFAULT_COMMENT = 'configured by junos_template'
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
|
|
||||||
argument_spec = dict(
|
|
||||||
src=dict(required=True, type='path'),
|
|
||||||
confirm=dict(default=0, type='int'),
|
|
||||||
comment=dict(default=DEFAULT_COMMENT),
|
|
||||||
action=dict(default='merge', choices=['merge', 'overwrite', 'replace']),
|
|
||||||
config_format=dict(choices=['text', 'set', 'xml'], default='text'),
|
|
||||||
backup=dict(default=False, type='bool'),
|
|
||||||
)
|
|
||||||
|
|
||||||
argument_spec.update(junos_argument_spec)
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
|
||||||
supports_check_mode=True)
|
|
||||||
|
|
||||||
warnings = list()
|
|
||||||
check_args(module, warnings)
|
|
||||||
|
|
||||||
result = {'changed': False, 'warnings': warnings}
|
|
||||||
|
|
||||||
commit = not module.check_mode
|
|
||||||
action = module.params['action']
|
|
||||||
src = module.params['src']
|
|
||||||
fmt = module.params['config_format']
|
|
||||||
|
|
||||||
if action == 'overwrite' and fmt == 'set':
|
|
||||||
module.fail_json(msg="overwrite cannot be used when format is set per junos-pyez documentation")
|
|
||||||
|
|
||||||
if module.params['backup']:
|
|
||||||
reply = get_configuration(module, format='set')
|
|
||||||
match = reply.find('.//configuration-set')
|
|
||||||
if match is None:
|
|
||||||
module.fail_json(msg='unable to retrieve device configuration')
|
|
||||||
result['__backup__'] = str(match.text).strip()
|
|
||||||
|
|
||||||
with locked_config(module):
|
|
||||||
diff = load_config(module, src, warnings, action=action, format=fmt)
|
|
||||||
if diff:
|
|
||||||
if commit:
|
|
||||||
commit_configuration(module)
|
|
||||||
else:
|
|
||||||
discard_changes(module)
|
|
||||||
result['changed'] = True
|
|
||||||
|
|
||||||
if module._diff:
|
|
||||||
result['diff'] = {'prepared': diff}
|
|
||||||
|
|
||||||
module.exit_json(**result)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,178 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
|
|
||||||
ANSIBLE_METADATA = {'metadata_version': '1.0',
|
|
||||||
'status': ['deprecated'],
|
|
||||||
'supported_by': 'community'}
|
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = """
|
|
||||||
---
|
|
||||||
module: nxos_template
|
|
||||||
version_added: "2.1"
|
|
||||||
author: "Peter Sprygada (@privateip)"
|
|
||||||
short_description: Manage Cisco NXOS device configurations
|
|
||||||
description:
|
|
||||||
- Manages network device configurations over SSH or NXAPI. This module
|
|
||||||
allows implementers to work with the device running-config. It
|
|
||||||
provides a way to push a set of commands onto a network device
|
|
||||||
by evaluating the current running-config and only pushing configuration
|
|
||||||
commands that are not already configured. The config source can
|
|
||||||
be a set of commands or a template.
|
|
||||||
deprecated: Deprecated in 2.2. Use M(nxos_config) instead.
|
|
||||||
options:
|
|
||||||
src:
|
|
||||||
description:
|
|
||||||
- The path to the config source. The source can be either a
|
|
||||||
file with config or a template that will be merged during
|
|
||||||
runtime. By default the task will search for the source
|
|
||||||
file in role or playbook root folder in templates directory.
|
|
||||||
required: false
|
|
||||||
default: null
|
|
||||||
force:
|
|
||||||
description:
|
|
||||||
- The force argument instructs the module to not consider the
|
|
||||||
current devices running-config. When set to true, this will
|
|
||||||
cause the module to push the contents of I(src) into the device
|
|
||||||
without first checking if already configured.
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
choices: [ "true", "false" ]
|
|
||||||
include_defaults:
|
|
||||||
description:
|
|
||||||
- The module, by default, will collect the current device
|
|
||||||
running-config to use as a base for comparisons to the commands
|
|
||||||
in I(src). Setting this value to true will cause the module
|
|
||||||
to issue the command C(show running-config all) to include all
|
|
||||||
device settings.
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
choices: [ "true", "false" ]
|
|
||||||
backup:
|
|
||||||
description:
|
|
||||||
- When this argument is configured true, the module will backup
|
|
||||||
the running-config from the node prior to making any changes.
|
|
||||||
The backup file will be written to backup_{{ hostname }} in
|
|
||||||
the root of the playbook directory.
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
choices: [ "true", "false" ]
|
|
||||||
config:
|
|
||||||
description:
|
|
||||||
- The module, by default, will connect to the remote device and
|
|
||||||
retrieve the current running-config to use as a base for comparing
|
|
||||||
against the contents of source. There are times when it is not
|
|
||||||
desirable to have the task get the current running-config for
|
|
||||||
every task in a playbook. The I(config) argument allows the
|
|
||||||
implementer to pass in the configuration to use as the base
|
|
||||||
config for comparison.
|
|
||||||
required: false
|
|
||||||
default: null
|
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = """
|
|
||||||
- name: push a configuration onto the device
|
|
||||||
nxos_template:
|
|
||||||
src: config.j2
|
|
||||||
|
|
||||||
- name: forceable push a configuration onto the device
|
|
||||||
nxos_template:
|
|
||||||
src: config.j2
|
|
||||||
force: yes
|
|
||||||
|
|
||||||
- name: provide the base configuration for comparison
|
|
||||||
nxos_template:
|
|
||||||
src: candidate_config.txt
|
|
||||||
config: current_config.txt
|
|
||||||
"""
|
|
||||||
|
|
||||||
RETURN = """
|
|
||||||
updates:
|
|
||||||
description: The set of commands that will be pushed to the remote device
|
|
||||||
returned: always
|
|
||||||
type: list
|
|
||||||
sample: ['...', '...']
|
|
||||||
|
|
||||||
responses:
|
|
||||||
description: The set of responses from issuing the commands on the device
|
|
||||||
returned: when not check_mode
|
|
||||||
type: list
|
|
||||||
sample: ['...', '...']
|
|
||||||
"""
|
|
||||||
from ansible.module_utils.nxos import load_config, get_config
|
|
||||||
from ansible.module_utils.nxos import nxos_argument_spec
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
|
||||||
from ansible.module_utils.netcfg import NetworkConfig, dumps
|
|
||||||
|
|
||||||
def get_current_config(module):
|
|
||||||
config = module.params.get('config')
|
|
||||||
if not config and not module.params['force']:
|
|
||||||
flags = []
|
|
||||||
if module.params['include_defaults']:
|
|
||||||
flags.append('all')
|
|
||||||
config = get_config(module, flags)
|
|
||||||
return config
|
|
||||||
|
|
||||||
def main():
|
|
||||||
""" main entry point for module execution
|
|
||||||
"""
|
|
||||||
argument_spec = dict(
|
|
||||||
src=dict(),
|
|
||||||
force=dict(default=False, type='bool'),
|
|
||||||
include_defaults=dict(default=True, type='bool'),
|
|
||||||
backup=dict(default=False, type='bool'),
|
|
||||||
config=dict(),
|
|
||||||
)
|
|
||||||
|
|
||||||
argument_spec.update(nxos_argument_spec)
|
|
||||||
|
|
||||||
mutually_exclusive = [('config', 'backup'), ('config', 'force')]
|
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
|
||||||
mutually_exclusive=mutually_exclusive,
|
|
||||||
supports_check_mode=True)
|
|
||||||
|
|
||||||
result = dict(changed=False)
|
|
||||||
|
|
||||||
candidate = NetworkConfig(contents=module.params['src'], indent=2)
|
|
||||||
|
|
||||||
contents = get_current_config(module)
|
|
||||||
if contents:
|
|
||||||
config = NetworkConfig(contents=contents, indent=2)
|
|
||||||
result['__backup__'] = str(contents)
|
|
||||||
|
|
||||||
if not module.params['force']:
|
|
||||||
commands = candidate.difference(config)
|
|
||||||
commands = dumps(commands, 'commands').split('\n')
|
|
||||||
commands = [str(c) for c in commands if c]
|
|
||||||
else:
|
|
||||||
commands = str(candidate).split('\n')
|
|
||||||
|
|
||||||
if commands:
|
|
||||||
if not module.check_mode:
|
|
||||||
load_config(module, commands)
|
|
||||||
result['changed'] = True
|
|
||||||
|
|
||||||
result['updates'] = commands
|
|
||||||
result['commands'] = commands
|
|
||||||
|
|
||||||
module.exit_json(**result)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,227 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
ANSIBLE_METADATA = {'metadata_version': '1.0',
|
|
||||||
'status': ['deprecated'],
|
|
||||||
'supported_by': 'community'}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = """
|
|
||||||
---
|
|
||||||
module: ops_template
|
|
||||||
version_added: "2.1"
|
|
||||||
author: "Peter Sprygada (@privateip)"
|
|
||||||
short_description: Push configuration to OpenSwitch
|
|
||||||
description:
|
|
||||||
- The OpenSwitch platform provides a library for pushing JSON structured
|
|
||||||
configuration files into the current running-config. This module
|
|
||||||
will read the current configuration from OpenSwitch and compare it
|
|
||||||
against a provided candidate configuration. If there are changes, the
|
|
||||||
candidate configuration is merged with the current configuration and
|
|
||||||
pushed into OpenSwitch
|
|
||||||
deprecated: Deprecated in 2.2. Use M(ops_config) instead.
|
|
||||||
extends_documentation_fragment: openswitch
|
|
||||||
options:
|
|
||||||
src:
|
|
||||||
description:
|
|
||||||
- The path to the config source. The source can be either a
|
|
||||||
file with config or a template that will be merged during
|
|
||||||
runtime. By default the task will search for the source
|
|
||||||
file in role or playbook root folder in templates directory.
|
|
||||||
required: true
|
|
||||||
force:
|
|
||||||
description:
|
|
||||||
- The force argument instructs the module to not consider the
|
|
||||||
current devices running-config. When set to true, this will
|
|
||||||
cause the module to push the contents of I(src) into the device
|
|
||||||
without first checking if already configured.
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
choices: ['yes', 'no']
|
|
||||||
backup:
|
|
||||||
description:
|
|
||||||
- When this argument is configured true, the module will backup
|
|
||||||
the running-config from the node prior to making any changes.
|
|
||||||
The backup file will be written to backups/ in
|
|
||||||
the root of the playbook directory.
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
choices: ['yes', 'no']
|
|
||||||
config:
|
|
||||||
description:
|
|
||||||
- The module, by default, will connect to the remote device and
|
|
||||||
retrieve the current running-config to use as a base for comparing
|
|
||||||
against the contents of source. There are times when it is not
|
|
||||||
desirable to have the task get the current running-config for
|
|
||||||
every task in a playbook. The I(config) argument allows the
|
|
||||||
implementer to pass in the configuration to use as the base
|
|
||||||
config for comparison.
|
|
||||||
required: false
|
|
||||||
default: null
|
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = """
|
|
||||||
- name: set hostname with file lookup
|
|
||||||
ops_template:
|
|
||||||
src: ./hostname.json
|
|
||||||
backup: yes
|
|
||||||
remote_user: admin
|
|
||||||
become: yes
|
|
||||||
|
|
||||||
- name: set hostname with var
|
|
||||||
ops_template:
|
|
||||||
src: "{{ config }}"
|
|
||||||
remote_user: admin
|
|
||||||
become: yes
|
|
||||||
"""
|
|
||||||
|
|
||||||
RETURN = """
|
|
||||||
updates:
|
|
||||||
description: The list of configuration updates to be merged
|
|
||||||
returned: always
|
|
||||||
type: dict
|
|
||||||
sample: {obj, obj}
|
|
||||||
responses:
|
|
||||||
description: returns the responses when configuring using cli
|
|
||||||
returned: when transport == cli
|
|
||||||
type: list
|
|
||||||
sample: [...]
|
|
||||||
"""
|
|
||||||
|
|
||||||
import ansible.module_utils.openswitch
|
|
||||||
from ansible.module_utils.netcfg import NetworkConfig, dumps
|
|
||||||
from ansible.module_utils.network import NetworkModule
|
|
||||||
from ansible.module_utils.openswitch import HAS_OPS
|
|
||||||
|
|
||||||
|
|
||||||
def get_config(module):
|
|
||||||
config = module.params['config'] or dict()
|
|
||||||
if not config and not module.params['force']:
|
|
||||||
config = module.config.get_config()
|
|
||||||
return config
|
|
||||||
|
|
||||||
|
|
||||||
def sort(val):
|
|
||||||
if isinstance(val, (list, set)):
|
|
||||||
return sorted(val)
|
|
||||||
return val
|
|
||||||
|
|
||||||
|
|
||||||
def diff(this, other, path=None):
|
|
||||||
updates = list()
|
|
||||||
path = path or list()
|
|
||||||
for key, value in this.items():
|
|
||||||
if key not in other:
|
|
||||||
other_value = other.get(key)
|
|
||||||
updates.append((list(path), key, value, other_value))
|
|
||||||
else:
|
|
||||||
if isinstance(this[key], dict):
|
|
||||||
path.append(key)
|
|
||||||
updates.extend(diff(this[key], other[key], list(path)))
|
|
||||||
path.pop()
|
|
||||||
else:
|
|
||||||
other_value = other.get(key)
|
|
||||||
if sort(this[key]) != sort(other_value):
|
|
||||||
updates.append((list(path), key, value, other_value))
|
|
||||||
return updates
|
|
||||||
|
|
||||||
|
|
||||||
def merge(changeset, config=None):
|
|
||||||
config = config or dict()
|
|
||||||
for path, key, value, _ in changeset:
|
|
||||||
current_level = config
|
|
||||||
for part in path:
|
|
||||||
if part not in current_level:
|
|
||||||
current_level[part] = dict()
|
|
||||||
current_level = current_level[part]
|
|
||||||
current_level[key] = value
|
|
||||||
return config
|
|
||||||
|
|
||||||
def main():
|
|
||||||
""" main entry point for module execution
|
|
||||||
"""
|
|
||||||
|
|
||||||
argument_spec = dict(
|
|
||||||
src=dict(type='str'),
|
|
||||||
force=dict(default=False, type='bool'),
|
|
||||||
backup=dict(default=False, type='bool'),
|
|
||||||
config=dict(type='dict'),
|
|
||||||
)
|
|
||||||
|
|
||||||
mutually_exclusive = [('config', 'backup'), ('config', 'force')]
|
|
||||||
|
|
||||||
module = NetworkModule(argument_spec=argument_spec,
|
|
||||||
mutually_exclusive=mutually_exclusive,
|
|
||||||
supports_check_mode=True)
|
|
||||||
|
|
||||||
if not module.params['transport'] and not HAS_OPS:
|
|
||||||
module.fail_json(msg='unable to import ops.dc library')
|
|
||||||
|
|
||||||
result = dict(changed=False)
|
|
||||||
|
|
||||||
contents = get_config(module)
|
|
||||||
result['_backup'] = contents
|
|
||||||
|
|
||||||
if module.params['transport'] in ['ssh', 'rest']:
|
|
||||||
config = contents
|
|
||||||
|
|
||||||
try:
|
|
||||||
src = module.from_json(module.params['src'])
|
|
||||||
except ValueError:
|
|
||||||
module.fail_json(msg='unable to load src due to json parsing error')
|
|
||||||
|
|
||||||
changeset = diff(src, config)
|
|
||||||
candidate = merge(changeset, config)
|
|
||||||
|
|
||||||
updates = dict()
|
|
||||||
for path, key, new_value, old_value in changeset:
|
|
||||||
path = '%s.%s' % ('.'.join(path), key)
|
|
||||||
updates[path] = str(new_value)
|
|
||||||
result['updates'] = updates
|
|
||||||
|
|
||||||
if changeset:
|
|
||||||
if not module.check_mode:
|
|
||||||
module.config(config)
|
|
||||||
result['changed'] = True
|
|
||||||
|
|
||||||
else:
|
|
||||||
candidate = NetworkConfig(contents=module.params['src'], indent=4)
|
|
||||||
|
|
||||||
if contents:
|
|
||||||
config = NetworkConfig(contents=contents, indent=4)
|
|
||||||
|
|
||||||
if not module.params['force']:
|
|
||||||
commands = candidate.difference(config)
|
|
||||||
commands = dumps(commands, 'commands').split('\n')
|
|
||||||
commands = [str(c) for c in commands if c]
|
|
||||||
else:
|
|
||||||
commands = str(candidate).split('\n')
|
|
||||||
|
|
||||||
if commands:
|
|
||||||
if not module.check_mode:
|
|
||||||
response = module.config(commands)
|
|
||||||
result['responses'] = response
|
|
||||||
result['changed'] = True
|
|
||||||
|
|
||||||
result['updates'] = commands
|
|
||||||
|
|
||||||
module.exit_json(**result)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,103 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright 2015 Peter Sprygada <psprygada@ansible.com>
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
import glob
|
|
||||||
import urlparse
|
|
||||||
|
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.plugins.action.eos import ActionModule as _ActionModule
|
|
||||||
|
|
||||||
|
|
||||||
class ActionModule(_ActionModule):
|
|
||||||
|
|
||||||
def run(self, tmp=None, task_vars=None):
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._handle_template()
|
|
||||||
except (ValueError, AttributeError) as exc:
|
|
||||||
return dict(failed=True, msg=exc.message)
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(tmp, task_vars)
|
|
||||||
|
|
||||||
if self._task.args.get('backup') and result.get('__backup__'):
|
|
||||||
# User requested backup and no error occurred in module.
|
|
||||||
# NOTE: If there is a parameter error, __backup__ key may not be in results.
|
|
||||||
self._write_backup(task_vars['inventory_hostname'], result['__backup__'])
|
|
||||||
|
|
||||||
if '__backup__' in result:
|
|
||||||
del result['__backup__']
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _get_working_path(self):
|
|
||||||
cwd = self._loader.get_basedir()
|
|
||||||
if self._task._role is not None:
|
|
||||||
cwd = self._task._role._role_path
|
|
||||||
return cwd
|
|
||||||
|
|
||||||
def _write_backup(self, host, contents):
|
|
||||||
backup_path = self._get_working_path() + '/backup'
|
|
||||||
if not os.path.exists(backup_path):
|
|
||||||
os.mkdir(backup_path)
|
|
||||||
for fn in glob.glob('%s/%s*' % (backup_path, host)):
|
|
||||||
os.remove(fn)
|
|
||||||
tstamp = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time()))
|
|
||||||
filename = '%s/%s_config.%s' % (backup_path, host, tstamp)
|
|
||||||
open(filename, 'w').write(contents)
|
|
||||||
|
|
||||||
def _handle_template(self):
|
|
||||||
src = self._task.args.get('src')
|
|
||||||
if not src:
|
|
||||||
raise ValueError('missing required arguments: src')
|
|
||||||
|
|
||||||
working_path = self._get_working_path()
|
|
||||||
|
|
||||||
if os.path.isabs(src) or urlparse.urlsplit(src).scheme:
|
|
||||||
source = src
|
|
||||||
else:
|
|
||||||
source = self._loader.path_dwim_relative(working_path, 'templates', src)
|
|
||||||
if not source:
|
|
||||||
source = self._loader.path_dwim_relative(working_path, src)
|
|
||||||
|
|
||||||
if not os.path.exists(source):
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(source, 'r') as f:
|
|
||||||
template_data = to_text(f.read())
|
|
||||||
except IOError:
|
|
||||||
return dict(failed=True, msg='unable to load src file')
|
|
||||||
|
|
||||||
# Create a template search path in the following order:
|
|
||||||
# [working_path, self_role_path, dependent_role_paths, dirname(source)]
|
|
||||||
searchpath = [working_path]
|
|
||||||
if self._task._role is not None:
|
|
||||||
searchpath.append(self._task._role._role_path)
|
|
||||||
if hasattr(self._task, "_block:"):
|
|
||||||
dep_chain = self._task._block.get_dep_chain()
|
|
||||||
if dep_chain is not None:
|
|
||||||
for role in dep_chain:
|
|
||||||
searchpath.append(role._role_path)
|
|
||||||
searchpath.append(os.path.dirname(source))
|
|
||||||
self._templar.environment.loader.searchpath = searchpath
|
|
||||||
self._task.args['src'] = self._templar.template(template_data)
|
|
|
@ -1,103 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright 2015 Peter Sprygada <psprygada@ansible.com>
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
import glob
|
|
||||||
import urlparse
|
|
||||||
|
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.plugins.action.ios import ActionModule as _ActionModule
|
|
||||||
|
|
||||||
|
|
||||||
class ActionModule(_ActionModule):
|
|
||||||
|
|
||||||
def run(self, tmp=None, task_vars=None):
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._handle_template()
|
|
||||||
except (ValueError, AttributeError) as exc:
|
|
||||||
return dict(failed=True, msg=exc.message)
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(tmp, task_vars)
|
|
||||||
|
|
||||||
if self._task.args.get('backup') and result.get('__backup__'):
|
|
||||||
# User requested backup and no error occurred in module.
|
|
||||||
# NOTE: If there is a parameter error, __backup__ key may not be in results.
|
|
||||||
self._write_backup(task_vars['inventory_hostname'], result['__backup__'])
|
|
||||||
|
|
||||||
if '__backup__' in result:
|
|
||||||
del result['__backup__']
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _get_working_path(self):
|
|
||||||
cwd = self._loader.get_basedir()
|
|
||||||
if self._task._role is not None:
|
|
||||||
cwd = self._task._role._role_path
|
|
||||||
return cwd
|
|
||||||
|
|
||||||
def _write_backup(self, host, contents):
|
|
||||||
backup_path = self._get_working_path() + '/backup'
|
|
||||||
if not os.path.exists(backup_path):
|
|
||||||
os.mkdir(backup_path)
|
|
||||||
for fn in glob.glob('%s/%s*' % (backup_path, host)):
|
|
||||||
os.remove(fn)
|
|
||||||
tstamp = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time()))
|
|
||||||
filename = '%s/%s_config.%s' % (backup_path, host, tstamp)
|
|
||||||
open(filename, 'w').write(contents)
|
|
||||||
|
|
||||||
def _handle_template(self):
|
|
||||||
src = self._task.args.get('src')
|
|
||||||
if not src:
|
|
||||||
raise ValueError('missing required arguments: src')
|
|
||||||
|
|
||||||
working_path = self._get_working_path()
|
|
||||||
|
|
||||||
if os.path.isabs(src) or urlparse.urlsplit(src).scheme:
|
|
||||||
source = src
|
|
||||||
else:
|
|
||||||
source = self._loader.path_dwim_relative(working_path, 'templates', src)
|
|
||||||
if not source:
|
|
||||||
source = self._loader.path_dwim_relative(working_path, src)
|
|
||||||
|
|
||||||
if not os.path.exists(source):
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(source, 'r') as f:
|
|
||||||
template_data = to_text(f.read())
|
|
||||||
except IOError:
|
|
||||||
return dict(failed=True, msg='unable to load src file')
|
|
||||||
|
|
||||||
# Create a template search path in the following order:
|
|
||||||
# [working_path, self_role_path, dependent_role_paths, dirname(source)]
|
|
||||||
searchpath = [working_path]
|
|
||||||
if self._task._role is not None:
|
|
||||||
searchpath.append(self._task._role._role_path)
|
|
||||||
if hasattr(self._task, "_block:"):
|
|
||||||
dep_chain = self._task._block.get_dep_chain()
|
|
||||||
if dep_chain is not None:
|
|
||||||
for role in dep_chain:
|
|
||||||
searchpath.append(role._role_path)
|
|
||||||
searchpath.append(os.path.dirname(source))
|
|
||||||
self._templar.environment.loader.searchpath = searchpath
|
|
||||||
self._task.args['src'] = self._templar.template(template_data)
|
|
|
@ -1,103 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright 2015 Peter Sprygada <psprygada@ansible.com>
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
import glob
|
|
||||||
import urlparse
|
|
||||||
|
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.plugins.action.iosxr import ActionModule as _ActionModule
|
|
||||||
|
|
||||||
|
|
||||||
class ActionModule(_ActionModule):
|
|
||||||
|
|
||||||
def run(self, tmp=None, task_vars=None):
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._handle_template()
|
|
||||||
except (ValueError, AttributeError) as exc:
|
|
||||||
return dict(failed=True, msg=exc.message)
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(tmp, task_vars)
|
|
||||||
|
|
||||||
if self._task.args.get('backup') and result.get('__backup__'):
|
|
||||||
# User requested backup and no error occurred in module.
|
|
||||||
# NOTE: If there is a parameter error, __backup__ key may not be in results.
|
|
||||||
self._write_backup(task_vars['inventory_hostname'], result['__backup__'])
|
|
||||||
|
|
||||||
if '__backup__' in result:
|
|
||||||
del result['__backup__']
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _get_working_path(self):
|
|
||||||
cwd = self._loader.get_basedir()
|
|
||||||
if self._task._role is not None:
|
|
||||||
cwd = self._task._role._role_path
|
|
||||||
return cwd
|
|
||||||
|
|
||||||
def _write_backup(self, host, contents):
|
|
||||||
backup_path = self._get_working_path() + '/backup'
|
|
||||||
if not os.path.exists(backup_path):
|
|
||||||
os.mkdir(backup_path)
|
|
||||||
for fn in glob.glob('%s/%s*' % (backup_path, host)):
|
|
||||||
os.remove(fn)
|
|
||||||
tstamp = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time()))
|
|
||||||
filename = '%s/%s_config.%s' % (backup_path, host, tstamp)
|
|
||||||
open(filename, 'w').write(contents)
|
|
||||||
|
|
||||||
def _handle_template(self):
|
|
||||||
src = self._task.args.get('src')
|
|
||||||
if not src:
|
|
||||||
raise ValueError('missing required arguments: src')
|
|
||||||
|
|
||||||
working_path = self._get_working_path()
|
|
||||||
|
|
||||||
if os.path.isabs(src) or urlparse.urlsplit(src).scheme:
|
|
||||||
source = src
|
|
||||||
else:
|
|
||||||
source = self._loader.path_dwim_relative(working_path, 'templates', src)
|
|
||||||
if not source:
|
|
||||||
source = self._loader.path_dwim_relative(working_path, src)
|
|
||||||
|
|
||||||
if not os.path.exists(source):
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(source, 'r') as f:
|
|
||||||
template_data = to_text(f.read())
|
|
||||||
except IOError:
|
|
||||||
return dict(failed=True, msg='unable to load src file')
|
|
||||||
|
|
||||||
# Create a template search path in the following order:
|
|
||||||
# [working_path, self_role_path, dependent_role_paths, dirname(source)]
|
|
||||||
searchpath = [working_path]
|
|
||||||
if self._task._role is not None:
|
|
||||||
searchpath.append(self._task._role._role_path)
|
|
||||||
if hasattr(self._task, "_block:"):
|
|
||||||
dep_chain = self._task._block.get_dep_chain()
|
|
||||||
if dep_chain is not None:
|
|
||||||
for role in dep_chain:
|
|
||||||
searchpath.append(role._role_path)
|
|
||||||
searchpath.append(os.path.dirname(source))
|
|
||||||
self._templar.environment.loader.searchpath = searchpath
|
|
||||||
self._task.args['src'] = self._templar.template(template_data)
|
|
|
@ -1,118 +0,0 @@
|
||||||
#
|
|
||||||
# (c) 2017 Red Hat, Inc.
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
import glob
|
|
||||||
import urlparse
|
|
||||||
|
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.plugins.action.junos import ActionModule as _ActionModule
|
|
||||||
|
|
||||||
|
|
||||||
class ActionModule(_ActionModule):
|
|
||||||
|
|
||||||
def run(self, tmp=None, task_vars=None):
|
|
||||||
|
|
||||||
src = self._task.args.get('src')
|
|
||||||
|
|
||||||
if self._task.args.get('config_format') is None:
|
|
||||||
if src.endswith('.xml'):
|
|
||||||
fmt = 'xml'
|
|
||||||
elif src.endswith('.set'):
|
|
||||||
fmt = 'set'
|
|
||||||
else:
|
|
||||||
fmt = 'text'
|
|
||||||
|
|
||||||
self._task.args['config_format'] = fmt
|
|
||||||
|
|
||||||
if self._task.args.get('comment') is None:
|
|
||||||
self._task.args['comment'] = self._task.name
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._handle_template()
|
|
||||||
except (ValueError, AttributeError) as exc:
|
|
||||||
return dict(failed=True, msg=exc.message)
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(tmp, task_vars)
|
|
||||||
|
|
||||||
if self._task.args.get('backup') and result.get('__backup__'):
|
|
||||||
# User requested backup and no error occurred in module.
|
|
||||||
# NOTE: If there is a parameter error, __backup__ key may not be in results.
|
|
||||||
self._write_backup(task_vars['inventory_hostname'], result['__backup__'])
|
|
||||||
|
|
||||||
if '__backup__' in result:
|
|
||||||
del result['__backup__']
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _get_working_path(self):
|
|
||||||
cwd = self._loader.get_basedir()
|
|
||||||
if self._task._role is not None:
|
|
||||||
cwd = self._task._role._role_path
|
|
||||||
return cwd
|
|
||||||
|
|
||||||
def _write_backup(self, host, contents):
|
|
||||||
backup_path = self._get_working_path() + '/backup'
|
|
||||||
if not os.path.exists(backup_path):
|
|
||||||
os.mkdir(backup_path)
|
|
||||||
for fn in glob.glob('%s/%s*' % (backup_path, host)):
|
|
||||||
os.remove(fn)
|
|
||||||
tstamp = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time()))
|
|
||||||
filename = '%s/%s_config.%s' % (backup_path, host, tstamp)
|
|
||||||
open(filename, 'w').write(contents)
|
|
||||||
|
|
||||||
def _handle_template(self):
|
|
||||||
src = self._task.args.get('src')
|
|
||||||
if not src:
|
|
||||||
raise ValueError('missing required arguments: src')
|
|
||||||
|
|
||||||
working_path = self._get_working_path()
|
|
||||||
|
|
||||||
if os.path.isabs(src) or urlparse.urlsplit(src).scheme:
|
|
||||||
source = src
|
|
||||||
else:
|
|
||||||
source = self._loader.path_dwim_relative(working_path, 'templates', src)
|
|
||||||
if not source:
|
|
||||||
source = self._loader.path_dwim_relative(working_path, src)
|
|
||||||
|
|
||||||
if not os.path.exists(source):
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(source, 'r') as f:
|
|
||||||
template_data = to_text(f.read())
|
|
||||||
except IOError:
|
|
||||||
return dict(failed=True, msg='unable to load src file')
|
|
||||||
|
|
||||||
# Create a template search path in the following order:
|
|
||||||
# [working_path, self_role_path, dependent_role_paths, dirname(source)]
|
|
||||||
searchpath = [working_path]
|
|
||||||
if self._task._role is not None:
|
|
||||||
searchpath.append(self._task._role._role_path)
|
|
||||||
if hasattr(self._task, "_block:"):
|
|
||||||
dep_chain = self._task._block.get_dep_chain()
|
|
||||||
if dep_chain is not None:
|
|
||||||
for role in dep_chain:
|
|
||||||
searchpath.append(role._role_path)
|
|
||||||
searchpath.append(os.path.dirname(source))
|
|
||||||
self._templar.environment.loader.searchpath = searchpath
|
|
||||||
self._task.args['src'] = self._templar.template(template_data)
|
|
|
@ -1,103 +0,0 @@
|
||||||
#
|
|
||||||
# (c) 2016 Red Hat Inc.
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
import glob
|
|
||||||
import urlparse
|
|
||||||
|
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.plugins.action.normal import ActionModule as _ActionModule
|
|
||||||
|
|
||||||
|
|
||||||
class ActionModule(_ActionModule):
|
|
||||||
|
|
||||||
def run(self, tmp=None, task_vars=None):
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._handle_template()
|
|
||||||
except (ValueError, AttributeError) as exc:
|
|
||||||
return dict(failed=True, msg=exc.message)
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(tmp, task_vars)
|
|
||||||
|
|
||||||
if self._task.args.get('backup') and result.get('__backup__'):
|
|
||||||
# User requested backup and no error occurred in module.
|
|
||||||
# NOTE: If there is a parameter error, __backup__ key may not be in results.
|
|
||||||
self._write_backup(task_vars['inventory_hostname'], result['__backup__'])
|
|
||||||
|
|
||||||
if '__backup__' in result:
|
|
||||||
del result['__backup__']
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _get_working_path(self):
|
|
||||||
cwd = self._loader.get_basedir()
|
|
||||||
if self._task._role is not None:
|
|
||||||
cwd = self._task._role._role_path
|
|
||||||
return cwd
|
|
||||||
|
|
||||||
def _write_backup(self, host, contents):
|
|
||||||
backup_path = self._get_working_path() + '/backup'
|
|
||||||
if not os.path.exists(backup_path):
|
|
||||||
os.mkdir(backup_path)
|
|
||||||
for fn in glob.glob('%s/%s*' % (backup_path, host)):
|
|
||||||
os.remove(fn)
|
|
||||||
tstamp = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time()))
|
|
||||||
filename = '%s/%s_config.%s' % (backup_path, host, tstamp)
|
|
||||||
open(filename, 'w').write(contents)
|
|
||||||
|
|
||||||
def _handle_template(self):
|
|
||||||
src = self._task.args.get('src')
|
|
||||||
if not src:
|
|
||||||
raise ValueError('missing required arguments: src')
|
|
||||||
|
|
||||||
working_path = self._get_working_path()
|
|
||||||
|
|
||||||
if os.path.isabs(src) or urlparse.urlsplit(src).scheme:
|
|
||||||
source = src
|
|
||||||
else:
|
|
||||||
source = self._loader.path_dwim_relative(working_path, 'templates', src)
|
|
||||||
if not source:
|
|
||||||
source = self._loader.path_dwim_relative(working_path, src)
|
|
||||||
|
|
||||||
if not os.path.exists(source):
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(source, 'r') as f:
|
|
||||||
template_data = to_text(f.read())
|
|
||||||
except IOError:
|
|
||||||
return dict(failed=True, msg='unable to load src file')
|
|
||||||
|
|
||||||
# Create a template search path in the following order:
|
|
||||||
# [working_path, self_role_path, dependent_role_paths, dirname(source)]
|
|
||||||
searchpath = [working_path]
|
|
||||||
if self._task._role is not None:
|
|
||||||
searchpath.append(self._task._role._role_path)
|
|
||||||
if hasattr(self._task, "_block:"):
|
|
||||||
dep_chain = self._task._block.get_dep_chain()
|
|
||||||
if dep_chain is not None:
|
|
||||||
for role in dep_chain:
|
|
||||||
searchpath.append(role._role_path)
|
|
||||||
searchpath.append(os.path.dirname(source))
|
|
||||||
self._templar.environment.loader.searchpath = searchpath
|
|
||||||
self._task.args['src'] = self._templar.template(template_data)
|
|
|
@ -1,103 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright 2015 Peter Sprygada <psprygada@ansible.com>
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
import glob
|
|
||||||
|
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
from ansible.module_utils.six.moves.urllib.parse import urlsplit
|
|
||||||
from ansible.plugins.action.nxos import ActionModule as _ActionModule
|
|
||||||
|
|
||||||
|
|
||||||
class ActionModule(_ActionModule):
|
|
||||||
|
|
||||||
def run(self, tmp=None, task_vars=None):
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._handle_template()
|
|
||||||
except (ValueError, AttributeError) as exc:
|
|
||||||
return dict(failed=True, msg=str(exc))
|
|
||||||
|
|
||||||
result = super(ActionModule, self).run(tmp, task_vars)
|
|
||||||
|
|
||||||
if self._task.args.get('backup') and result.get('__backup__'):
|
|
||||||
# User requested backup and no error occurred in module.
|
|
||||||
# NOTE: If there is a parameter error, __backup__ key may not be in results.
|
|
||||||
self._write_backup(task_vars['inventory_hostname'], result['__backup__'])
|
|
||||||
|
|
||||||
if '__backup__' in result:
|
|
||||||
del result['__backup__']
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _get_working_path(self):
|
|
||||||
cwd = self._loader.get_basedir()
|
|
||||||
if self._task._role is not None:
|
|
||||||
cwd = self._task._role._role_path
|
|
||||||
return cwd
|
|
||||||
|
|
||||||
def _write_backup(self, host, contents):
|
|
||||||
backup_path = self._get_working_path() + '/backup'
|
|
||||||
if not os.path.exists(backup_path):
|
|
||||||
os.mkdir(backup_path)
|
|
||||||
for fn in glob.glob('%s/%s*' % (backup_path, host)):
|
|
||||||
os.remove(fn)
|
|
||||||
tstamp = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time()))
|
|
||||||
filename = '%s/%s_config.%s' % (backup_path, host, tstamp)
|
|
||||||
open(filename, 'w').write(contents)
|
|
||||||
|
|
||||||
def _handle_template(self):
|
|
||||||
src = self._task.args.get('src')
|
|
||||||
if not src:
|
|
||||||
raise ValueError('missing required arguments: src')
|
|
||||||
|
|
||||||
working_path = self._get_working_path()
|
|
||||||
|
|
||||||
if os.path.isabs(src) or urlsplit(src).scheme:
|
|
||||||
source = src
|
|
||||||
else:
|
|
||||||
source = self._loader.path_dwim_relative(working_path, 'templates', src)
|
|
||||||
if not source:
|
|
||||||
source = self._loader.path_dwim_relative(working_path, src)
|
|
||||||
|
|
||||||
if not os.path.exists(source):
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(source, 'r') as f:
|
|
||||||
template_data = to_text(f.read())
|
|
||||||
except IOError:
|
|
||||||
return dict(failed=True, msg='unable to load src file')
|
|
||||||
|
|
||||||
# Create a template search path in the following order:
|
|
||||||
# [working_path, self_role_path, dependent_role_paths, dirname(source)]
|
|
||||||
searchpath = [working_path]
|
|
||||||
if self._task._role is not None:
|
|
||||||
searchpath.append(self._task._role._role_path)
|
|
||||||
if hasattr(self._task, "_block:"):
|
|
||||||
dep_chain = self._task._block.get_dep_chain()
|
|
||||||
if dep_chain is not None:
|
|
||||||
for role in dep_chain:
|
|
||||||
searchpath.append(role._role_path)
|
|
||||||
searchpath.append(os.path.dirname(source))
|
|
||||||
self._templar.environment.loader.searchpath = searchpath
|
|
||||||
self._task.args['src'] = self._templar.template(template_data)
|
|
|
@ -1,50 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright 2015 Peter Sprygada <psprygada@ansible.com>
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
from ansible.module_utils.six import string_types
|
|
||||||
from ansible.plugins.action import ActionBase
|
|
||||||
from ansible.plugins.action.net_template import ActionModule as NetActionModule
|
|
||||||
|
|
||||||
|
|
||||||
class ActionModule(NetActionModule, ActionBase):
|
|
||||||
|
|
||||||
def run(self, tmp=None, task_vars=None):
|
|
||||||
if self._connection.transport == 'local':
|
|
||||||
return super(ActionModule, self).run(tmp, task_vars)
|
|
||||||
|
|
||||||
result = dict(changed=False)
|
|
||||||
|
|
||||||
if isinstance(self._task.args['src'], string_types):
|
|
||||||
self._handle_template()
|
|
||||||
|
|
||||||
result.update(self._execute_module(module_name=self._task.action,
|
|
||||||
module_args=self._task.args, task_vars=task_vars))
|
|
||||||
|
|
||||||
if self._task.args.get('backup') and result.get('_backup'):
|
|
||||||
contents = json.dumps(result['_backup'], indent=4)
|
|
||||||
self._write_backup(task_vars['inventory_hostname'], contents)
|
|
||||||
|
|
||||||
if '_backup' in result:
|
|
||||||
del result['_backup']
|
|
||||||
|
|
||||||
return result
|
|
|
@ -40,15 +40,6 @@
|
||||||
failed_modules: "{{ failed_modules }} + [ 'eos_config' ]"
|
failed_modules: "{{ failed_modules }} + [ 'eos_config' ]"
|
||||||
test_failed: true
|
test_failed: true
|
||||||
|
|
||||||
- block:
|
|
||||||
- include_role:
|
|
||||||
name: eos_template
|
|
||||||
when: "limit_to in ['*', 'eos_template']"
|
|
||||||
rescue:
|
|
||||||
- set_fact:
|
|
||||||
failed_modules: "{{ failed_modules }} + [ 'eos_template' ]"
|
|
||||||
test_failed: true
|
|
||||||
|
|
||||||
- block:
|
- block:
|
||||||
- include_role:
|
- include_role:
|
||||||
name: eos_facts
|
name: eos_facts
|
||||||
|
|
|
@ -49,15 +49,6 @@
|
||||||
failed_modules: "{{ failed_modules }} + [ 'ios_facts' ]"
|
failed_modules: "{{ failed_modules }} + [ 'ios_facts' ]"
|
||||||
test_failed: true
|
test_failed: true
|
||||||
|
|
||||||
- block:
|
|
||||||
- include_role:
|
|
||||||
name: ios_template
|
|
||||||
when: "limit_to in ['*', 'ios_template']"
|
|
||||||
rescue:
|
|
||||||
- set_fact:
|
|
||||||
failed_modules: "{{ failed_modules }} + [ 'ios_template' ]"
|
|
||||||
test_failed: true
|
|
||||||
|
|
||||||
- block:
|
- block:
|
||||||
- include_role:
|
- include_role:
|
||||||
name: ios_system
|
name: ios_system
|
||||||
|
|
|
@ -42,15 +42,6 @@
|
||||||
failed_modules: "{{ failed_modules }} + [ 'iosxr_facts' ]"
|
failed_modules: "{{ failed_modules }} + [ 'iosxr_facts' ]"
|
||||||
test_failed: true
|
test_failed: true
|
||||||
|
|
||||||
- block:
|
|
||||||
- include_role:
|
|
||||||
name: iosxr_template
|
|
||||||
when: "limit_to in ['*', 'iosxr_template']"
|
|
||||||
rescue:
|
|
||||||
- set_fact:
|
|
||||||
failed_modules: "{{ failed_modules }} + [ 'iosxr_template' ]"
|
|
||||||
test_failed: true
|
|
||||||
|
|
||||||
- block:
|
- block:
|
||||||
- include_role:
|
- include_role:
|
||||||
name: iosxr_system
|
name: iosxr_system
|
||||||
|
|
|
@ -61,14 +61,6 @@
|
||||||
failed_modules: "{{ failed_modules }} + [ 'junos_rpc' ]"
|
failed_modules: "{{ failed_modules }} + [ 'junos_rpc' ]"
|
||||||
test_failed: true
|
test_failed: true
|
||||||
|
|
||||||
- block:
|
|
||||||
- include_role:
|
|
||||||
name: junos_template
|
|
||||||
when: "limit_to in ['*', 'junos_template']"
|
|
||||||
rescue:
|
|
||||||
- set_fact:
|
|
||||||
failed_modules: "{{ failed_modules }} + [ 'junos_template' ]"
|
|
||||||
test_failed: true
|
|
||||||
- block:
|
- block:
|
||||||
- include_role:
|
- include_role:
|
||||||
name: junos_vlan
|
name: junos_vlan
|
||||||
|
|
|
@ -42,15 +42,6 @@
|
||||||
failed_modules: "{{ failed_modules }} + [ 'nxos_facts' ]"
|
failed_modules: "{{ failed_modules }} + [ 'nxos_facts' ]"
|
||||||
test_failed: true
|
test_failed: true
|
||||||
|
|
||||||
- block:
|
|
||||||
- include_role:
|
|
||||||
name: nxos_template
|
|
||||||
when: "limit_to in ['*', 'nxos_template']"
|
|
||||||
rescue:
|
|
||||||
- set_fact:
|
|
||||||
failed_modules: "{{ failed_modules }} + [ 'nxos_template' ]"
|
|
||||||
test_failed: true
|
|
||||||
|
|
||||||
- block:
|
- block:
|
||||||
- include_role:
|
- include_role:
|
||||||
name: nxos_nxapi
|
name: nxos_nxapi
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
---
|
|
||||||
testcase: "*"
|
|
|
@ -1,2 +0,0 @@
|
||||||
dependencies:
|
|
||||||
- prepare_eos_tests
|
|
|
@ -1,15 +0,0 @@
|
||||||
---
|
|
||||||
- name: collect all cli test cases
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/tests/cli"
|
|
||||||
patterns: "{{ testcase }}.yaml"
|
|
||||||
register: test_cases
|
|
||||||
|
|
||||||
- name: set test_items
|
|
||||||
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
|
|
||||||
|
|
||||||
- name: run test case
|
|
||||||
include: "{{ test_case_to_run }}"
|
|
||||||
with_items: "{{ test_items }}"
|
|
||||||
loop_control:
|
|
||||||
loop_var: test_case_to_run
|
|
|
@ -1,28 +0,0 @@
|
||||||
---
|
|
||||||
- name: collect all eapi test cases
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/tests/eapi"
|
|
||||||
patterns: "{{ testcase }}.yaml"
|
|
||||||
register: test_cases
|
|
||||||
|
|
||||||
- name: set test_items
|
|
||||||
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
|
|
||||||
|
|
||||||
- name: enable eapi
|
|
||||||
eos_eapi:
|
|
||||||
http: yes
|
|
||||||
https: yes
|
|
||||||
local_http: no
|
|
||||||
enable_socket: yes
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
|
|
||||||
- name: run test case
|
|
||||||
include: "{{ test_case_to_run }}"
|
|
||||||
with_items: "{{ test_items }}"
|
|
||||||
loop_control:
|
|
||||||
loop_var: test_case_to_run
|
|
||||||
|
|
||||||
- name: disable eapi
|
|
||||||
eos_eapi:
|
|
||||||
state: stopped
|
|
||||||
provider: "{{ cli }}"
|
|
|
@ -1,3 +0,0 @@
|
||||||
---
|
|
||||||
- { include: cli.yaml, tags: ['cli'] }
|
|
||||||
- { include: eapi.yaml, tags: ['eapi'] }
|
|
|
@ -1,4 +0,0 @@
|
||||||
interface Ethernet2
|
|
||||||
description this is a test
|
|
||||||
shutdown
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
interface Ethernet2
|
|
||||||
description test description from ansible
|
|
||||||
shutdown
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
interface Ethernet2
|
|
||||||
description this is a test
|
|
||||||
no shutdown
|
|
|
@ -1,4 +0,0 @@
|
||||||
interface Ethernet2
|
|
||||||
description this is a test
|
|
||||||
shutdown
|
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START cli/backup.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
eos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- no shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2
|
|
||||||
match: none
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
|
|
||||||
- name: collect any backup files
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/backup"
|
|
||||||
pattern: "{{ inventory_hostname_short }}_config*"
|
|
||||||
register: backup_files
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- name: delete backup files
|
|
||||||
file:
|
|
||||||
path: "{{ item.path }}"
|
|
||||||
state: absent
|
|
||||||
with_items: "{{backup_files.files|default([])}}"
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
eos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
backup: yes
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: collect any backup files
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/backup"
|
|
||||||
pattern: "{{ inventory_hostname_short }}_config*"
|
|
||||||
register: backup_files
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "backup_files.files is defined"
|
|
||||||
|
|
||||||
- debug: msg="END cli/backup.yaml"
|
|
|
@ -1,36 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START cli/basic.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
eos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- no shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2
|
|
||||||
match: none
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
eos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with config
|
|
||||||
eos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == false"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- debug: msg="END cli/basic.yaml"
|
|
|
@ -1,42 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START cli/defaults.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
eos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2
|
|
||||||
match: none
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
|
|
||||||
- name: configure device with defaults included
|
|
||||||
eos_template:
|
|
||||||
src: defaults/config.j2
|
|
||||||
include_defaults: yes
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- debug: var=result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with defaults included
|
|
||||||
eos_template:
|
|
||||||
src: defaults/config.j2
|
|
||||||
include_defaults: yes
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- debug: var=result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == false"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- debug: msg="END cli/defaults.yaml"
|
|
|
@ -1,38 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START cli/force.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
eos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- no shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2
|
|
||||||
match: none
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
eos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
force: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with config
|
|
||||||
eos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
force: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- debug: msg="END cli/force.yaml"
|
|
|
@ -1,50 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START eapi/backup.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
eos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- no shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2
|
|
||||||
match: none
|
|
||||||
provider: "{{ eapi }}"
|
|
||||||
|
|
||||||
- name: collect any backup files
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/backup"
|
|
||||||
pattern: "{{ inventory_hostname_short }}_config*"
|
|
||||||
register: backup_files
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- name: delete backup files
|
|
||||||
file:
|
|
||||||
path: "{{ item.path }}"
|
|
||||||
state: absent
|
|
||||||
with_items: "{{backup_files.files|default([])}}"
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
eos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
backup: yes
|
|
||||||
provider: "{{ eapi }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: collect any backup files
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/backup"
|
|
||||||
pattern: "{{ inventory_hostname_short }}_config*"
|
|
||||||
register: backup_files
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "backup_files.files is defined"
|
|
||||||
|
|
||||||
- debug: msg="END eapi/backup.yaml"
|
|
|
@ -1,36 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START eapi/basic.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
eos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- no shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2
|
|
||||||
match: none
|
|
||||||
provider: "{{ eapi }}"
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
eos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ eapi }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with config
|
|
||||||
eos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ eapi }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == false"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- debug: msg="END eapi/basic.yaml"
|
|
|
@ -1,42 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START eapi/defaults.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
eos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2
|
|
||||||
match: none
|
|
||||||
provider: "{{ eapi }}"
|
|
||||||
|
|
||||||
- name: configure device with defaults included
|
|
||||||
eos_template:
|
|
||||||
src: defaults/config.j2
|
|
||||||
include_defaults: yes
|
|
||||||
provider: "{{ eapi }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
#- debug: var=result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with defaults included
|
|
||||||
eos_template:
|
|
||||||
src: defaults/config.j2
|
|
||||||
include_defaults: yes
|
|
||||||
provider: "{{ eapi }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
#- debug: var=result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == false"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- debug: msg="END eapi/defaults.yaml"
|
|
|
@ -1,38 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START eapi/force.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
eos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- no shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2
|
|
||||||
match: none
|
|
||||||
provider: "{{ eapi }}"
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
eos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ eapi }}"
|
|
||||||
force: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with config
|
|
||||||
eos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ eapi }}"
|
|
||||||
force: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- debug: msg="END eapi/force.yaml"
|
|
|
@ -1,3 +0,0 @@
|
||||||
---
|
|
||||||
testcase: "*"
|
|
||||||
test_items: []
|
|
|
@ -1,2 +0,0 @@
|
||||||
dependencies:
|
|
||||||
- prepare_ios_tests
|
|
|
@ -1,16 +0,0 @@
|
||||||
---
|
|
||||||
- name: collect all cli test cases
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/tests/cli"
|
|
||||||
patterns: "{{ testcase }}.yaml"
|
|
||||||
register: test_cases
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- name: set test_items
|
|
||||||
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
|
|
||||||
|
|
||||||
- name: run test case
|
|
||||||
include: "{{ test_case_to_run }}"
|
|
||||||
with_items: "{{ test_items }}"
|
|
||||||
loop_control:
|
|
||||||
loop_var: test_case_to_run
|
|
|
@ -1,2 +0,0 @@
|
||||||
---
|
|
||||||
- { include: cli.yaml, tags: ['cli'] }
|
|
|
@ -1,4 +0,0 @@
|
||||||
interface Loopback999
|
|
||||||
description this is a test
|
|
||||||
shutdown
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
interface Loopback999
|
|
||||||
description this is a test
|
|
||||||
no shutdown
|
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START cli/backup.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
ios_config:
|
|
||||||
commands:
|
|
||||||
- no interface Loopback999
|
|
||||||
match: none
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- name: collect any backup files
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/backup"
|
|
||||||
pattern: "{{ inventory_hostname_short }}_config*"
|
|
||||||
register: backup_files
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- name: delete backup files
|
|
||||||
file:
|
|
||||||
path: "{{ item.path }}"
|
|
||||||
state: absent
|
|
||||||
with_items: "{{backup_files.files|default([])}}"
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
ios_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
backup: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: collect any backup files
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/backup"
|
|
||||||
pattern: "{{ inventory_hostname_short }}_config*"
|
|
||||||
register: backup_files
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "backup_files.files is defined"
|
|
||||||
|
|
||||||
- name: teardown
|
|
||||||
ios_config:
|
|
||||||
commands:
|
|
||||||
- no interface Loopback999
|
|
||||||
match: none
|
|
||||||
|
|
||||||
- debug: msg="END cli/backup.yaml"
|
|
|
@ -1,37 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START cli/basic.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
ios_config:
|
|
||||||
commands:
|
|
||||||
- no interface Loopback999
|
|
||||||
match: none
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
ios_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with config
|
|
||||||
ios_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == false"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: teardown
|
|
||||||
ios_config:
|
|
||||||
commands:
|
|
||||||
- no interface Loopback999
|
|
||||||
match: none
|
|
||||||
|
|
||||||
- debug: msg="END cli/basic.yaml"
|
|
|
@ -1,37 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START cli/defaults.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
ios_config:
|
|
||||||
commands: no interface Loopback999
|
|
||||||
match: none
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- name: configure device with defaults included
|
|
||||||
ios_template:
|
|
||||||
src: defaults/config.j2
|
|
||||||
include_defaults: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with defaults included
|
|
||||||
ios_template:
|
|
||||||
src: defaults/config.j2
|
|
||||||
include_defaults: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == false"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: teardown
|
|
||||||
ios_config:
|
|
||||||
commands: no interface Loopback999
|
|
||||||
match: none
|
|
||||||
|
|
||||||
- debug: msg="END cli/defaults.yaml"
|
|
|
@ -1,39 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START cli/force.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
ios_config:
|
|
||||||
commands:
|
|
||||||
- no interface Loopback999
|
|
||||||
match: none
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
ios_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
force: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with config
|
|
||||||
ios_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
force: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: teardown
|
|
||||||
ios_config:
|
|
||||||
commands:
|
|
||||||
- no interface Loopback999
|
|
||||||
match: none
|
|
||||||
|
|
||||||
- debug: msg="END cli/force.yaml"
|
|
|
@ -1,3 +0,0 @@
|
||||||
---
|
|
||||||
testcase: "*"
|
|
||||||
test_items: []
|
|
|
@ -1,2 +0,0 @@
|
||||||
dependencies:
|
|
||||||
- prepare_iosxr_tests
|
|
|
@ -1,16 +0,0 @@
|
||||||
---
|
|
||||||
- name: collect all cli test cases
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/tests/cli"
|
|
||||||
patterns: "{{ testcase }}.yaml"
|
|
||||||
register: test_cases
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- name: set test_items
|
|
||||||
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
|
|
||||||
|
|
||||||
- name: run test case
|
|
||||||
include: "{{ test_case_to_run }}"
|
|
||||||
with_items: "{{ test_items }}"
|
|
||||||
loop_control:
|
|
||||||
loop_var: test_case_to_run
|
|
|
@ -1,2 +0,0 @@
|
||||||
---
|
|
||||||
- { include: cli.yaml, tags: ['cli'] }
|
|
|
@ -1,5 +0,0 @@
|
||||||
hostname {{ inventory_hostname_short }}
|
|
||||||
!
|
|
||||||
interface Loopback999
|
|
||||||
description this is a test
|
|
||||||
shutdown
|
|
|
@ -1,52 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START cli/backup.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
iosxr_config:
|
|
||||||
commands:
|
|
||||||
- no interface Loopback999
|
|
||||||
match: none
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- name: collect any backup files
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/backup"
|
|
||||||
pattern: "{{ inventory_hostname_short }}_config*"
|
|
||||||
register: backup_files
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- name: delete backup files
|
|
||||||
file:
|
|
||||||
path: "{{ item.path }}"
|
|
||||||
state: absent
|
|
||||||
with_items: "{{backup_files.files|default([])}}"
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
iosxr_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
backup: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: collect any backup files
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/backup"
|
|
||||||
pattern: "{{ inventory_hostname_short }}_config*"
|
|
||||||
register: backup_files
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "backup_files.files is defined"
|
|
||||||
|
|
||||||
- name: teardown
|
|
||||||
iosxr_config:
|
|
||||||
commands:
|
|
||||||
- no interface Loopback999
|
|
||||||
match: none
|
|
||||||
|
|
||||||
- debug: msg="END cli/backup.yaml"
|
|
|
@ -1,36 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START cli/basic.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
iosxr_config:
|
|
||||||
commands:
|
|
||||||
- no interface Loopback999
|
|
||||||
match: none
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
iosxr_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with config
|
|
||||||
iosxr_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == false"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: teardown
|
|
||||||
iosxr_config:
|
|
||||||
commands:
|
|
||||||
- no interface Loopback999
|
|
||||||
match: none
|
|
||||||
|
|
||||||
- debug: msg="END cli/basic.yaml"
|
|
|
@ -1,38 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START cli/force.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
iosxr_config:
|
|
||||||
commands:
|
|
||||||
- no interface Loopback999
|
|
||||||
match: none
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
iosxr_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
force: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with config
|
|
||||||
iosxr_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
force: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: teardown
|
|
||||||
iosxr_config:
|
|
||||||
commands:
|
|
||||||
- no interface Loopback999
|
|
||||||
match: none
|
|
||||||
|
|
||||||
- debug: msg="END cli/force.yaml"
|
|
|
@ -1,3 +0,0 @@
|
||||||
---
|
|
||||||
testcase: "*"
|
|
||||||
test_cases: []
|
|
|
@ -1,2 +0,0 @@
|
||||||
---
|
|
||||||
- { include: netconf.yaml, tags: ['netconf'] }
|
|
|
@ -1,15 +0,0 @@
|
||||||
---
|
|
||||||
- name: collect netconf test cases
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/tests/netconf"
|
|
||||||
patterns: "{{ testcase }}.yaml"
|
|
||||||
register: test_cases
|
|
||||||
|
|
||||||
- name: set test_items
|
|
||||||
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
|
|
||||||
|
|
||||||
- name: run test case
|
|
||||||
include: "{{ test_case_to_run }}"
|
|
||||||
with_items: "{{ test_items }}"
|
|
||||||
loop_control:
|
|
||||||
loop_var: test_case_to_run
|
|
|
@ -1,10 +0,0 @@
|
||||||
interfaces {
|
|
||||||
lo0 {
|
|
||||||
unit 0 {
|
|
||||||
family inet {
|
|
||||||
address 1.1.1.1/32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START netconf/backup.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
junos_config:
|
|
||||||
lines:
|
|
||||||
- set system host-name {{ inventory_hostname_short }}
|
|
||||||
- delete interfaces lo0
|
|
||||||
provider: "{{ netconf }}"
|
|
||||||
|
|
||||||
- name: collect any backup files
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/backup"
|
|
||||||
pattern: "{{ inventory_hostname_short }}_config*"
|
|
||||||
register: backup_files
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- name: delete backup files
|
|
||||||
file:
|
|
||||||
path: "{{ item.path }}"
|
|
||||||
state: absent
|
|
||||||
with_items: "{{backup_files.files|default([])}}"
|
|
||||||
|
|
||||||
- name: configure using template with backup
|
|
||||||
junos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
backup: yes
|
|
||||||
provider: "{{ netconf }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "'1.1.1.1/32' in result.diff.prepared"
|
|
||||||
|
|
||||||
- name: collect any backup files
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/backup"
|
|
||||||
pattern: "{{ inventory_hostname_short }}_config*"
|
|
||||||
register: backup_files
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "backup_files.files is defined"
|
|
||||||
|
|
||||||
- name: teardown
|
|
||||||
junos_config:
|
|
||||||
lines:
|
|
||||||
- set system host-name {{ inventory_hostname_short }}
|
|
||||||
- delete interfaces lo0
|
|
||||||
provider: "{{ netconf }}"
|
|
||||||
|
|
||||||
- debug: msg="END netconf/backup.yaml"
|
|
|
@ -1,39 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START netconf/basic.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
junos_config:
|
|
||||||
lines:
|
|
||||||
- set system host-name {{ inventory_hostname_short }}
|
|
||||||
- delete interfaces lo0
|
|
||||||
provider: "{{ netconf }}"
|
|
||||||
|
|
||||||
- name: configure basic config template
|
|
||||||
junos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ netconf }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "'1.1.1.1/32' in result.diff.prepared"
|
|
||||||
|
|
||||||
- name: check basic config template idempotent
|
|
||||||
junos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ netconf }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == false"
|
|
||||||
|
|
||||||
- name: teardown
|
|
||||||
junos_config:
|
|
||||||
lines:
|
|
||||||
- set system host-name {{ inventory_hostname_short }}
|
|
||||||
- delete interfaces lo0
|
|
||||||
provider: "{{ netconf }}"
|
|
||||||
|
|
||||||
- debug: msg="END netconf/basic.yaml"
|
|
|
@ -1,43 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START netconf/force.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
junos_config:
|
|
||||||
lines:
|
|
||||||
- set system host-name {{ inventory_hostname_short }}
|
|
||||||
- delete interfaces lo0
|
|
||||||
provider: "{{ netconf }}"
|
|
||||||
|
|
||||||
- name: configure basic config template
|
|
||||||
junos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ netconf }}"
|
|
||||||
action: replace
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "'1.1.1.1/32' in result.diff.prepared"
|
|
||||||
|
|
||||||
- name: check basic config template idempotent
|
|
||||||
junos_template:
|
|
||||||
src: basic/config-update.j2
|
|
||||||
action: replace
|
|
||||||
provider: "{{ netconf }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "'1.1.1.1/32' in result.diff.prepared"
|
|
||||||
|
|
||||||
- name: teardown
|
|
||||||
junos_config:
|
|
||||||
lines:
|
|
||||||
- set system host-name {{ inventory_hostname_short }}
|
|
||||||
- delete interfaces lo0
|
|
||||||
action: replace
|
|
||||||
provider: "{{ netconf }}"
|
|
||||||
|
|
||||||
- debug: msg="END netconf/force.yaml"
|
|
|
@ -1,3 +0,0 @@
|
||||||
---
|
|
||||||
testcase: "*"
|
|
||||||
test_items: []
|
|
|
@ -1,2 +0,0 @@
|
||||||
dependencies:
|
|
||||||
- prepare_nxos_tests
|
|
|
@ -1,15 +0,0 @@
|
||||||
---
|
|
||||||
- name: collect all cli test cases
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/tests/cli"
|
|
||||||
patterns: "{{ testcase }}.yaml"
|
|
||||||
register: test_cases
|
|
||||||
|
|
||||||
- name: set test_items
|
|
||||||
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
|
|
||||||
|
|
||||||
- name: run test case
|
|
||||||
include: "{{ test_case_to_run }}"
|
|
||||||
with_items: "{{ test_items }}"
|
|
||||||
loop_control:
|
|
||||||
loop_var: test_case_to_run
|
|
|
@ -1,3 +0,0 @@
|
||||||
---
|
|
||||||
- { include: cli.yaml, tags: ['cli'] }
|
|
||||||
- { include: nxapi.yaml, tags: ['nxapi'] }
|
|
|
@ -1,28 +0,0 @@
|
||||||
---
|
|
||||||
- name: collect all nxapi test cases
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/tests/nxapi"
|
|
||||||
patterns: "{{ testcase }}.yaml"
|
|
||||||
register: test_cases
|
|
||||||
|
|
||||||
- name: set test_items
|
|
||||||
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
|
|
||||||
|
|
||||||
- name: enable nxapi
|
|
||||||
nxos_config:
|
|
||||||
lines:
|
|
||||||
- feature nxapi
|
|
||||||
- nxapi http port 80
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
|
|
||||||
- name: run test case
|
|
||||||
include: "{{ test_case_to_run }}"
|
|
||||||
with_items: "{{ test_items }}"
|
|
||||||
loop_control:
|
|
||||||
loop_var: test_case_to_run
|
|
||||||
|
|
||||||
- name: disable nxapi
|
|
||||||
nxos_config:
|
|
||||||
lines:
|
|
||||||
- no feature nxapi
|
|
||||||
provider: "{{ cli }}"
|
|
|
@ -1,4 +0,0 @@
|
||||||
interface Ethernet2/5
|
|
||||||
description this is a test
|
|
||||||
shutdown
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
interface Ethernet2/5
|
|
||||||
description test description from ansible
|
|
||||||
shutdown
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
interface Ethernet2/5
|
|
||||||
description this is a test
|
|
||||||
no shutdown
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
interface Ethernet2/5
|
|
||||||
description this is a test
|
|
||||||
shutdown
|
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START cli/backup.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
nxos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- no shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2/5
|
|
||||||
match: none
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
|
|
||||||
- name: collect any backup files
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/backup"
|
|
||||||
pattern: "{{ inventory_hostname_short }}_config*"
|
|
||||||
register: backup_files
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- name: delete backup files
|
|
||||||
file:
|
|
||||||
path: "{{ item.path }}"
|
|
||||||
state: absent
|
|
||||||
with_items: "{{backup_files.files|default([])}}"
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
nxos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
backup: yes
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: collect any backup files
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/backup"
|
|
||||||
pattern: "{{ inventory_hostname_short }}_config*"
|
|
||||||
register: backup_files
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "backup_files.files is defined"
|
|
||||||
|
|
||||||
- debug: msg="END cli/backup.yaml"
|
|
|
@ -1,36 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START cli/basic.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
nxos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- no shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2/5
|
|
||||||
match: none
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
nxos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with config
|
|
||||||
nxos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == false"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- debug: msg="END cli/basic.yaml"
|
|
|
@ -1,42 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START cli/defaults.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
nxos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2/5
|
|
||||||
match: none
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
|
|
||||||
- name: configure device with defaults included
|
|
||||||
nxos_template:
|
|
||||||
src: defaults/config.j2
|
|
||||||
include_defaults: yes
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- debug: var=result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with defaults included
|
|
||||||
nxos_template:
|
|
||||||
src: defaults/config.j2
|
|
||||||
include_defaults: yes
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- debug: var=result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == false"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- debug: msg="END cli/defaults.yaml"
|
|
|
@ -1,38 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START cli/force.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
nxos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- no shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2/5
|
|
||||||
match: none
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
nxos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
force: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with config
|
|
||||||
nxos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ cli }}"
|
|
||||||
force: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- debug: msg="END cli/force.yaml"
|
|
|
@ -1,50 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START nxapi/backup.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
nxos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- no shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2/5
|
|
||||||
match: none
|
|
||||||
provider: "{{ nxapi }}"
|
|
||||||
|
|
||||||
- name: collect any backup files
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/backup"
|
|
||||||
pattern: "{{ inventory_hostname_short }}_config*"
|
|
||||||
register: backup_files
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- name: delete backup files
|
|
||||||
file:
|
|
||||||
path: "{{ item.path }}"
|
|
||||||
state: absent
|
|
||||||
with_items: "{{backup_files.files|default([])}}"
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
nxos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
backup: yes
|
|
||||||
provider: "{{ nxapi }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: collect any backup files
|
|
||||||
find:
|
|
||||||
paths: "{{ role_path }}/backup"
|
|
||||||
pattern: "{{ inventory_hostname_short }}_config*"
|
|
||||||
register: backup_files
|
|
||||||
delegate_to: localhost
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "backup_files.files is defined"
|
|
||||||
|
|
||||||
- debug: msg="END nxapi/backup.yaml"
|
|
|
@ -1,36 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START nxapi/basic.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
nxos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- no shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2/5
|
|
||||||
match: none
|
|
||||||
provider: "{{ nxapi }}"
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
nxos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ nxapi }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with config
|
|
||||||
nxos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ nxapi }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == false"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- debug: msg="END nxapi/basic.yaml"
|
|
|
@ -1,42 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START nxapi/defaults.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
nxos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2/5
|
|
||||||
match: none
|
|
||||||
provider: "{{ nxapi }}"
|
|
||||||
|
|
||||||
- name: configure device with defaults included
|
|
||||||
nxos_template:
|
|
||||||
src: defaults/config.j2
|
|
||||||
include_defaults: yes
|
|
||||||
provider: "{{ nxapi }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- debug: var=result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with defaults included
|
|
||||||
nxos_template:
|
|
||||||
src: defaults/config.j2
|
|
||||||
include_defaults: yes
|
|
||||||
provider: "{{ nxapi }}"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- debug: var=result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == false"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- debug: msg="END nxapi/defaults.yaml"
|
|
|
@ -1,38 +0,0 @@
|
||||||
---
|
|
||||||
- debug: msg="START nxapi/force.yaml"
|
|
||||||
|
|
||||||
- name: setup
|
|
||||||
nxos_config:
|
|
||||||
commands:
|
|
||||||
- no description
|
|
||||||
- no shutdown
|
|
||||||
parents:
|
|
||||||
- interface Ethernet2/5
|
|
||||||
match: none
|
|
||||||
provider: "{{ nxapi }}"
|
|
||||||
|
|
||||||
- name: configure device with config
|
|
||||||
nxos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ nxapi }}"
|
|
||||||
force: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- name: check device with config
|
|
||||||
nxos_template:
|
|
||||||
src: basic/config.j2
|
|
||||||
provider: "{{ nxapi }}"
|
|
||||||
force: yes
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- "result.changed == true"
|
|
||||||
- "result.updates is defined"
|
|
||||||
|
|
||||||
- debug: msg="END nxapi/force.yaml"
|
|
|
@ -298,7 +298,6 @@ lib/ansible/modules/network/cumulus/_cl_ports.py
|
||||||
lib/ansible/modules/network/cumulus/nclu.py
|
lib/ansible/modules/network/cumulus/nclu.py
|
||||||
lib/ansible/modules/net_tools/dnsimple.py
|
lib/ansible/modules/net_tools/dnsimple.py
|
||||||
lib/ansible/modules/net_tools/dnsmadeeasy.py
|
lib/ansible/modules/net_tools/dnsmadeeasy.py
|
||||||
lib/ansible/modules/network/eos/_eos_template.py
|
|
||||||
lib/ansible/modules/network/eos/eos_banner.py
|
lib/ansible/modules/network/eos/eos_banner.py
|
||||||
lib/ansible/modules/network/eos/eos_command.py
|
lib/ansible/modules/network/eos/eos_command.py
|
||||||
lib/ansible/modules/network/eos/eos_config.py
|
lib/ansible/modules/network/eos/eos_config.py
|
||||||
|
@ -312,13 +311,11 @@ lib/ansible/modules/network/fortios/fortios_config.py
|
||||||
lib/ansible/modules/network/fortios/fortios_ipv4_policy.py
|
lib/ansible/modules/network/fortios/fortios_ipv4_policy.py
|
||||||
lib/ansible/modules/network/illumos/dladm_iptun.py
|
lib/ansible/modules/network/illumos/dladm_iptun.py
|
||||||
lib/ansible/modules/network/illumos/dladm_linkprop.py
|
lib/ansible/modules/network/illumos/dladm_linkprop.py
|
||||||
lib/ansible/modules/network/ios/_ios_template.py
|
|
||||||
lib/ansible/modules/network/ios/ios_banner.py
|
lib/ansible/modules/network/ios/ios_banner.py
|
||||||
lib/ansible/modules/network/ios/ios_command.py
|
lib/ansible/modules/network/ios/ios_command.py
|
||||||
lib/ansible/modules/network/ios/ios_facts.py
|
lib/ansible/modules/network/ios/ios_facts.py
|
||||||
lib/ansible/modules/network/ios/ios_system.py
|
lib/ansible/modules/network/ios/ios_system.py
|
||||||
lib/ansible/modules/network/ios/ios_vrf.py
|
lib/ansible/modules/network/ios/ios_vrf.py
|
||||||
lib/ansible/modules/network/iosxr/_iosxr_template.py
|
|
||||||
lib/ansible/modules/network/iosxr/iosxr_command.py
|
lib/ansible/modules/network/iosxr/iosxr_command.py
|
||||||
lib/ansible/modules/network/iosxr/iosxr_config.py
|
lib/ansible/modules/network/iosxr/iosxr_config.py
|
||||||
lib/ansible/modules/network/iosxr/iosxr_facts.py
|
lib/ansible/modules/network/iosxr/iosxr_facts.py
|
||||||
|
@ -337,7 +334,6 @@ lib/ansible/modules/network/netvisor/pn_vrouterif.py
|
||||||
lib/ansible/modules/network/netvisor/pn_vrouterlbif.py
|
lib/ansible/modules/network/netvisor/pn_vrouterlbif.py
|
||||||
lib/ansible/modules/net_tools/nmcli.py
|
lib/ansible/modules/net_tools/nmcli.py
|
||||||
lib/ansible/modules/network/nxos/_nxos_mtu.py
|
lib/ansible/modules/network/nxos/_nxos_mtu.py
|
||||||
lib/ansible/modules/network/nxos/_nxos_template.py
|
|
||||||
lib/ansible/modules/network/nxos/nxos_aaa_server.py
|
lib/ansible/modules/network/nxos/nxos_aaa_server.py
|
||||||
lib/ansible/modules/network/nxos/nxos_aaa_server_host.py
|
lib/ansible/modules/network/nxos/nxos_aaa_server_host.py
|
||||||
lib/ansible/modules/network/nxos/nxos_command.py
|
lib/ansible/modules/network/nxos/nxos_command.py
|
||||||
|
@ -374,7 +370,6 @@ lib/ansible/modules/network/nxos/nxos_vtp_domain.py
|
||||||
lib/ansible/modules/network/nxos/nxos_vtp_password.py
|
lib/ansible/modules/network/nxos/nxos_vtp_password.py
|
||||||
lib/ansible/modules/network/nxos/nxos_vtp_version.py
|
lib/ansible/modules/network/nxos/nxos_vtp_version.py
|
||||||
lib/ansible/modules/net_tools/omapi_host.py
|
lib/ansible/modules/net_tools/omapi_host.py
|
||||||
lib/ansible/modules/network/openswitch/_ops_template.py
|
|
||||||
lib/ansible/modules/network/openswitch/ops_command.py
|
lib/ansible/modules/network/openswitch/ops_command.py
|
||||||
lib/ansible/modules/network/openswitch/ops_config.py
|
lib/ansible/modules/network/openswitch/ops_config.py
|
||||||
lib/ansible/modules/network/openswitch/ops_facts.py
|
lib/ansible/modules/network/openswitch/ops_facts.py
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
!
|
|
||||||
hostname router
|
|
||||||
!
|
|
||||||
interface GigabitEthernet0/0
|
|
||||||
ip address 1.2.3.4 255.255.255.0
|
|
||||||
description test string
|
|
||||||
!
|
|
||||||
interface GigabitEthernet0/1
|
|
||||||
ip address 6.7.8.9 255.255.255.0
|
|
||||||
description test string
|
|
||||||
shutdown
|
|
||||||
!
|
|
|
@ -1,13 +0,0 @@
|
||||||
!
|
|
||||||
hostname router
|
|
||||||
!
|
|
||||||
interface GigabitEthernet0/0
|
|
||||||
ip address 1.2.3.4 255.255.255.0
|
|
||||||
description test string
|
|
||||||
no shutdown
|
|
||||||
!
|
|
||||||
interface GigabitEthernet0/1
|
|
||||||
ip address 6.7.8.9 255.255.255.0
|
|
||||||
description test string
|
|
||||||
shutdown
|
|
||||||
!
|
|
|
@ -1,11 +0,0 @@
|
||||||
!
|
|
||||||
hostname foo
|
|
||||||
!
|
|
||||||
interface GigabitEthernet0/0
|
|
||||||
no ip address
|
|
||||||
!
|
|
||||||
interface GigabitEthernet0/1
|
|
||||||
ip address 6.7.8.9 255.255.255.0
|
|
||||||
description test string
|
|
||||||
shutdown
|
|
||||||
!
|
|
|
@ -1,87 +0,0 @@
|
||||||
#
|
|
||||||
# (c) 2016 Red Hat Inc.
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# Make coding more python3-ish
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
from ansible.compat.tests.mock import patch
|
|
||||||
from ansible.modules.network.ios import _ios_template
|
|
||||||
from .ios_module import TestIosModule, load_fixture, set_module_args
|
|
||||||
|
|
||||||
|
|
||||||
class TestIosTemplateModule(TestIosModule):
|
|
||||||
|
|
||||||
module = _ios_template
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.mock_get_config = patch('ansible.modules.network.ios._ios_template.get_config')
|
|
||||||
self.get_config = self.mock_get_config.start()
|
|
||||||
|
|
||||||
self.mock_load_config = patch('ansible.modules.network.ios._ios_template.load_config')
|
|
||||||
self.load_config = self.mock_load_config.start()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.mock_get_config.stop()
|
|
||||||
self.mock_load_config.stop()
|
|
||||||
|
|
||||||
def load_fixtures(self, commands=None):
|
|
||||||
config_file = 'ios_template_config.cfg'
|
|
||||||
self.get_config.return_value = load_fixture(config_file)
|
|
||||||
self.load_config.return_value = None
|
|
||||||
|
|
||||||
def test_ios_template_unchanged(self):
|
|
||||||
src = load_fixture('ios_template_config.cfg')
|
|
||||||
set_module_args(dict(src=src))
|
|
||||||
self.execute_module()
|
|
||||||
|
|
||||||
def test_ios_template_simple(self):
|
|
||||||
src = load_fixture('ios_template_src.cfg')
|
|
||||||
set_module_args(dict(src=src))
|
|
||||||
commands = ['hostname foo',
|
|
||||||
'interface GigabitEthernet0/0',
|
|
||||||
'no ip address']
|
|
||||||
self.execute_module(changed=True, commands=commands)
|
|
||||||
|
|
||||||
def test_ios_template_force(self):
|
|
||||||
src = load_fixture('ios_template_config.cfg')
|
|
||||||
set_module_args(dict(src=src, force=True))
|
|
||||||
commands = [str(s).strip() for s in src.split('\n') if s and s != '!']
|
|
||||||
self.execute_module(changed=True, commands=commands)
|
|
||||||
self.assertFalse(self.get_config.called)
|
|
||||||
|
|
||||||
def test_ios_template_backup(self):
|
|
||||||
set_module_args(dict(backup=True))
|
|
||||||
result = self.execute_module()
|
|
||||||
self.assertIn('__backup__', result)
|
|
||||||
|
|
||||||
def test_ios_template_config(self):
|
|
||||||
src = load_fixture('ios_template_config.cfg')
|
|
||||||
config = 'hostname router'
|
|
||||||
set_module_args(dict(src=src, config=config))
|
|
||||||
commands = ['interface GigabitEthernet0/0',
|
|
||||||
'ip address 1.2.3.4 255.255.255.0',
|
|
||||||
'description test string',
|
|
||||||
'interface GigabitEthernet0/1',
|
|
||||||
'ip address 6.7.8.9 255.255.255.0',
|
|
||||||
'description test string',
|
|
||||||
'shutdown']
|
|
||||||
self.execute_module(changed=True, commands=commands)
|
|
||||||
self.assertFalse(self.get_config.called)
|
|
|
@ -1,12 +0,0 @@
|
||||||
!
|
|
||||||
hostname router
|
|
||||||
!
|
|
||||||
interface GigabitEthernet0/0
|
|
||||||
ip address 1.2.3.4 255.255.255.0
|
|
||||||
description test string
|
|
||||||
!
|
|
||||||
interface GigabitEthernet0/1
|
|
||||||
ip address 6.7.8.9 255.255.255.0
|
|
||||||
description test string
|
|
||||||
shutdown
|
|
||||||
!
|
|
|
@ -1,11 +0,0 @@
|
||||||
!
|
|
||||||
hostname foo
|
|
||||||
!
|
|
||||||
interface GigabitEthernet0/0
|
|
||||||
no ip address
|
|
||||||
!
|
|
||||||
interface GigabitEthernet0/1
|
|
||||||
ip address 6.7.8.9 255.255.255.0
|
|
||||||
description test string
|
|
||||||
shutdown
|
|
||||||
!
|
|
|
@ -1,87 +0,0 @@
|
||||||
#
|
|
||||||
# (c) 2016 Red Hat Inc.
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# Make coding more python3-ish
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
from ansible.compat.tests.mock import patch
|
|
||||||
from .iosxr_module import TestIosxrModule, load_fixture, set_module_args
|
|
||||||
from ansible.modules.network.iosxr import _iosxr_template
|
|
||||||
|
|
||||||
|
|
||||||
class TestIosxrTemplateModule(TestIosxrModule):
|
|
||||||
|
|
||||||
module = _iosxr_template
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.mock_get_config = patch('ansible.modules.network.iosxr._iosxr_template.get_config')
|
|
||||||
self.get_config = self.mock_get_config.start()
|
|
||||||
|
|
||||||
self.mock_load_config = patch('ansible.modules.network.iosxr._iosxr_template.load_config')
|
|
||||||
self.load_config = self.mock_load_config.start()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.mock_get_config.stop()
|
|
||||||
self.mock_load_config.stop()
|
|
||||||
|
|
||||||
def load_fixtures(self, commands=None):
|
|
||||||
config_file = 'iosxr_template_config.cfg'
|
|
||||||
self.get_config.return_value = load_fixture(config_file)
|
|
||||||
self.load_config.return_value = None
|
|
||||||
|
|
||||||
def test_iosxr_template_unchanged(self):
|
|
||||||
src = load_fixture('iosxr_template_config.cfg')
|
|
||||||
set_module_args(dict(src=src))
|
|
||||||
self.execute_module()
|
|
||||||
|
|
||||||
def test_iosxr_template_simple(self):
|
|
||||||
src = load_fixture('iosxr_template_src.cfg')
|
|
||||||
set_module_args(dict(src=src))
|
|
||||||
commands = ['hostname foo',
|
|
||||||
'interface GigabitEthernet0/0',
|
|
||||||
'no ip address']
|
|
||||||
self.execute_module(changed=True, commands=commands)
|
|
||||||
|
|
||||||
def test_iosxr_template_force(self):
|
|
||||||
src = load_fixture('iosxr_template_config.cfg')
|
|
||||||
set_module_args(dict(src=src, force=True))
|
|
||||||
commands = [str(s).strip() for s in src.split('\n') if s and s != '!']
|
|
||||||
self.execute_module(changed=True, commands=commands)
|
|
||||||
self.assertFalse(self.get_config.called)
|
|
||||||
|
|
||||||
def test_iosxr_template_backup(self):
|
|
||||||
set_module_args(dict(backup=True))
|
|
||||||
result = self.execute_module()
|
|
||||||
self.assertIn('__backup__', result)
|
|
||||||
|
|
||||||
def test_iosxr_template_config(self):
|
|
||||||
src = load_fixture('iosxr_template_config.cfg')
|
|
||||||
config = 'hostname router'
|
|
||||||
set_module_args(dict(src=src, config=config))
|
|
||||||
commands = ['interface GigabitEthernet0/0',
|
|
||||||
'ip address 1.2.3.4 255.255.255.0',
|
|
||||||
'description test string',
|
|
||||||
'interface GigabitEthernet0/1',
|
|
||||||
'ip address 6.7.8.9 255.255.255.0',
|
|
||||||
'description test string',
|
|
||||||
'shutdown']
|
|
||||||
self.execute_module(changed=False)
|
|
||||||
self.assertTrue(self.get_config.called)
|
|
Loading…
Reference in a new issue