Skip to content

Commit

Permalink
Fortios file only mode + integration tests (#23275)
Browse files Browse the repository at this point in the history
* WIP file_mode

* WIP

* Add file_mode + integration tests

* fix pep8

* Update doc fragments
Create mutualy_exclusive param
Fix yamllint problem in tests

* Add aliases file + main playbook for fortios

* Install pyfg before running tests

* Install pyfg before running tests in role

* Remove pre_task as it's done in roles

* Force pyFG minimal version for python3

* role_path not role_dir :(

* Change requirements

* Specify Error type when error on import

* Bug in pygf library with python 2.5 (PR is waiting spotify/pyfg#19)

* Bad requirement format

* still bad format -_-'

* remove test/integration/fortios.py (auto generated by tests)
missing new lines at end of file

* pyFG is now fixed in 0.50
  • Loading branch information
bjolivot authored and gundalow committed May 9, 2017
1 parent e342b28 commit e99815e
Show file tree
Hide file tree
Showing 8 changed files with 3,368 additions and 42 deletions.
106 changes: 70 additions & 36 deletions lib/ansible/module_utils/fortios.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@
from pyFG import FortiOS, FortiConfig
from pyFG.exceptions import CommandExecutionException, FailedCommit
HAS_PYFG=True
except:
except ImportError:
HAS_PYFG=False

fortios_argument_spec = dict(
host = dict(required=True ),
username = dict(required=True ),
password = dict(required=True, type='str', no_log=True ),
file_mode = dict(type='bool', default=False),
config_file = dict(type='path'),
host = dict( ),
username = dict( ),
password = dict(type='str', no_log=True ),
timeout = dict(type='int', default=60),
vdom = dict(type='str', default=None ),
backup = dict(type='bool', default=False),
Expand All @@ -53,9 +55,16 @@
)

fortios_required_if = [
['file_mode', False, ['host', 'username', 'password']],
['file_mode', True, ['config_file']],
['backup', True , ['backup_path'] ],
]

fortios_mutually_exclusive = [
['config_file', 'host'],
['config_file', 'username'],
['config_file', 'password']
]

fortios_error_codes = {
'-3':"Object not found",
Expand Down Expand Up @@ -96,39 +105,55 @@ def __init__(self, module):


def _connect(self):
host = self.module.params['host']
username = self.module.params['username']
password = self.module.params['password']
timeout = self.module.params['timeout']
vdom = self.module.params['vdom']
if self.module.params['file_mode']:
self.forti_device = FortiOS('')
else:
host = self.module.params['host']
username = self.module.params['username']
password = self.module.params['password']
timeout = self.module.params['timeout']
vdom = self.module.params['vdom']

self.forti_device = FortiOS(host, username=username, password=password, timeout=timeout, vdom=vdom)
self.forti_device = FortiOS(host, username=username, password=password, timeout=timeout, vdom=vdom)

try:
self.forti_device.open()
except Exception:
e = get_exception()
self.module.fail_json(msg='Error connecting device. %s' % e)
try:
self.forti_device.open()
except Exception:
e = get_exception()
self.module.fail_json(msg='Error connecting device. %s' % e)


def load_config(self, path):
self._connect()
self.path = path
#get config
try:
self.forti_device.load_config(path=path)
self.result['running_config'] = self.forti_device.running_config.to_text()
except Exception:
self.forti_device.close()
e = get_exception()
self.module.fail_json(msg='Error reading running config. %s' % e)
self._connect()
#load in file_mode
if self.module.params['file_mode']:
try:
f = open(self.module.params['config_file'], 'r')
running = f.read()
f.close()
except IOError:
e = get_exception()
self.module.fail_json(msg='Error reading configuration file. %s' % e)
self.forti_device.load_config(config_text=running, path = path)

#backup if needed
if self.module.params['backup']:
backup(self.module, self.result['running_config'])
else:
#get config
try:
self.forti_device.load_config(path=path)
except Exception:
self.forti_device.close()
e = get_exception()
self.module.fail_json(msg='Error reading running config. %s' % e)

#set configs in object
self.result['running_config'] = self.forti_device.running_config.to_text()
self.candidate_config = self.forti_device.candidate_config

#backup if needed
if self.module.params['backup']:
backup(self.module, self.forti_device.running_config.to_text())


def apply_changes(self):
change_string = self.forti_device.compare_config()
Expand All @@ -138,16 +163,25 @@ def apply_changes(self):

#Commit if not check mode
if change_string and not self.module.check_mode:
try:
self.forti_device.commit()
except FailedCommit:
#Something's wrong (rollback is automatic)
self.forti_device.close()
e = get_exception()
error_list = self.get_error_infos(e)
self.module.fail_json(msg_error_list=error_list, msg="Unable to commit change, check your args, the error was %s" % e.message )
if self.module.params['file_mode']:
try:
f = open(self.module.params['config_file'], 'w')
f.write(self.candidate_config.to_text())
f.close
except IOError:
e = get_exception()
self.module.fail_json(msg='Error writing configuration file. %s' % e)
else:
try:
self.forti_device.commit()
except FailedCommit:
#Something's wrong (rollback is automatic)
self.forti_device.close()
e = get_exception()
error_list = self.get_error_infos(e)
self.module.fail_json(msg_error_list=error_list, msg="Unable to commit change, check your args, the error was %s" % e.message )

self.forti_device.close()
self.forti_device.close()
self.module.exit_json(**self.result)


Expand Down
19 changes: 13 additions & 6 deletions lib/ansible/utils/module_docs_fragments/fortios.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,25 @@ class ModuleDocFragment(object):
# Standard files documentation fragment
DOCUMENTATION = """
options:
file_mode:
description:
- Don't connect to any device, only use I(config_file) as input and Output.
default: false
type: bool
version_added: "2.4"
config_file:
description:
- Path to configuration file. Required when I(file_mode) is True.
version_added: "2.4"
host:
description:
- Specifies the DNS hostname or IP address for connecting to the remote fortios device.
required: true
- Specifies the DNS hostname or IP address for connecting to the remote fortios device. Required when I(file_mode) is False.
username:
description:
- Configures the username used to authenticate to the remote device.
required: true
- Configures the username used to authenticate to the remote device. Required when I(file_mode) is True.
password:
description:
- Specifies the password used to authenticate to the remote device.
required: true
- Specifies the password used to authenticate to the remote device. Required when I(file_mode) is True.
timeout:
description:
- Timeout in seconds for connecting to the remote device.
Expand Down
1 change: 1 addition & 0 deletions test/integration/targets/fortios_ipv4_policy/aliases
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
posix/ci/group1
Loading

0 comments on commit e99815e

Please sign in to comment.