Skip to content

Commit 59c691c

Browse files
committed
Merge pull request #478 from zancas/version_check_clean_commits
Version check clean commits
2 parents 26b95f8 + 3b96a2e commit 59c691c

18 files changed

Lines changed: 91 additions & 25 deletions

conftest.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414
#
1515

1616
from f5.bigip import BigIP
17+
import mock
1718
import pytest
1819

20+
from icontrol.session import iControlRESTSession
21+
1922

2023
def pytest_addoption(parser):
2124
parser.addoption("--bigip", action="store",
@@ -33,6 +36,19 @@ def pytest_addoption(parser):
3336
default='11.6.0')
3437

3538

39+
@pytest.fixture
40+
def fakeicontrolsession(monkeypatch):
41+
class Response(object):
42+
def json(self):
43+
return {'selfLink': 'https://localhost/mgmt/tm/sys?ver=11.6.0'}
44+
fakesessionclass = mock.create_autospec(iControlRESTSession, spec_set=True)
45+
fakesessioninstance =\
46+
mock.create_autospec(iControlRESTSession('A', 'B'), spec_set=True)
47+
fakesessioninstance.get = mock.MagicMock(return_value=Response())
48+
fakesessionclass.return_value = fakesessioninstance
49+
monkeypatch.setattr('f5.bigip.iControlRESTSession', fakesessionclass)
50+
51+
3652
@pytest.fixture
3753
def opt_bigip(request):
3854
return request.config.getoption("--bigip")

f5/bigip/__init__.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818

1919

2020
from icontrol.session import iControlRESTSession
21+
from urlparse import parse_qs
22+
from urlparse import urlparse
23+
2124

2225
from f5.bigip.cm import Cm
2326
from f5.bigip.resource import PathElement
@@ -54,8 +57,10 @@ def __init__(self, hostname, username, password, **kwargs):
5457
'bigip': self,
5558
'icontrol_version': icontrol_version,
5659
'username': username,
57-
'password': password
60+
'password': password,
61+
'tmos_version': None,
5862
}
63+
self._get_tmos_version()
5964

6065
@property
6166
def hostname(self):
@@ -65,6 +70,18 @@ def hostname(self):
6570
def icontrol_version(self):
6671
return self._meta_data['icontrol_version']
6772

73+
@property
74+
def tmos_version(self):
75+
return self._meta_data['tmos_version']
76+
77+
def _get_tmos_version(self):
78+
connect = self._meta_data['bigip']._meta_data['icr_session']
79+
base_uri = self._meta_data['uri'] + 'tm/sys/'
80+
response = connect.get(base_uri)
81+
ver = response.json()
82+
version = parse_qs(urlparse(ver['selfLink']).query)['ver'][0]
83+
self._meta_data['tmos_version'] = version
84+
6885

6986
class BigIP(ManagementRoot):
7087
"""A shim class used to access the default config resources in 'mgmt/tm.'

f5/bigip/cm/autodeploy/test/test_software_image_uploads.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
CHUNKSIZE = 20
2525

2626

27-
def test_software_image_uploads_80a(tmpdir):
27+
def test_software_image_uploads_80a(tmpdir, fakeicontrolsession):
2828
filepath = tmpdir.mkdir('testdir').join('eightya.iso')
2929
filepath.write(80*'a')
3030
mr = ManagementRoot('FAKENETLOC', 'FAKENAME', 'FAKEPASSWORD')
@@ -37,7 +37,7 @@ def test_software_image_uploads_80a(tmpdir):
3737
assert d == 'a'*CHUNKSIZE
3838

3939

40-
def test_software_image_uploads_70a(tmpdir):
40+
def test_software_image_uploads_70a(tmpdir, fakeicontrolsession):
4141
filepath = tmpdir.mkdir('testdir').join('seventya.iso')
4242
filepath.write(70*'a')
4343
mr = ManagementRoot('FAKENETLOC', 'FAKENAME', 'FAKEPASSWORD')
@@ -53,7 +53,7 @@ def test_software_image_uploads_70a(tmpdir):
5353
assert 10*'a' == lchunk
5454

5555

56-
def test_non_ISO_extension(tmpdir):
56+
def test_non_ISO_extension(tmpdir, fakeicontrolsession):
5757
filepath = tmpdir.mkdir('testdir').join('wrong.name')
5858
mr = ManagementRoot('FAKENETLOC', 'FAKENAME', 'FAKEPASSWORD')
5959
sius = mr.cm.autodeploy.software_image_uploads

f5/bigip/mixins.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ class UnsupportedMethod(F5SDKError):
3131
pass
3232

3333

34+
class UnsupportedTmosVersion(F5SDKError):
35+
"""Raise the error if a class of an API is instantiated,
36+
37+
on a TMOS version where API was not yet implemented/supported.
38+
"""
39+
pass
40+
41+
3442
class LazyAttributesRequired(F5SDKError):
3543
"""Raised when a object accesses a lazy attribute that is not listed"""
3644
pass
@@ -101,10 +109,20 @@ def __getattr__(container, name):
101109
if name == lazy_attribute.__name__.lower():
102110
attribute = lazy_attribute(container)
103111
bases = [base.__name__ for base in lazy_attribute.__bases__]
112+
# Doing version check per each resource
113+
container._check_supported_versions(attribute)
104114
if 'Resource' not in bases:
105115
setattr(container, name, attribute)
106116
return attribute
107117

118+
def _check_supported_versions(container, attribute):
119+
tmos_v = container._meta_data['bigip'].tmos_version
120+
if tmos_v not in attribute._meta_data['supported_versions']:
121+
error = "There was an attempt to access API which " \
122+
"has not been implemented or supported " \
123+
"in the device's TMOS version: {}".format(tmos_v)
124+
raise UnsupportedTmosVersion(error)
125+
108126

109127
class ExclusiveAttributesMixin(object):
110128
"""Overrides ``__setattr__`` to remove exclusive attrs from the object."""

f5/bigip/resource.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ class PathElement(LazyAttributeMixin):
162162
those elements and does not support any of the CURDLE methods that
163163
the other objects do.
164164
"""
165+
165166
def __init__(self, container):
166167
self._meta_data = {
167168
'container': container,
@@ -170,6 +171,9 @@ def __init__(self, container):
170171
'icontrol_version': container._meta_data['icontrol_version']
171172
}
172173
self._set_meta_data_uri()
174+
# Supported versions for each class will be defined here.
175+
# List can be modified downstream in each sub-class
176+
self._meta_data['supported_versions'] = set(['11.6.0', '12.0.0'])
173177

174178
def _set_meta_data_uri(self):
175179
base_uri = self.__class__.__name__.lower()

f5/bigip/shared/test/test_file_uploads.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
FileMustNotHaveDotISOExtension
2323

2424

25-
def test_file_upload_80a(tmpdir):
25+
def test_file_upload_80a(tmpdir, fakeicontrolsession):
2626
filepath = tmpdir.mkdir('testdir').join('eightya.txt')
2727
filepath.write(80*'a')
2828
mr = ManagementRoot('FAKENETLOC', 'FAKENAME', 'FAKEPASSWORD')
@@ -35,7 +35,7 @@ def test_file_upload_80a(tmpdir):
3535
assert d == 'aaaaaaaaaaaaaaaaaaaa'
3636

3737

38-
def test_file_upload_70a(tmpdir):
38+
def test_file_upload_70a(tmpdir, fakeicontrolsession):
3939
filepath = tmpdir.mkdir('testdir').join('seventya.txt')
4040
filepath.write(70*'a')
4141
mr = ManagementRoot('FAKENETLOC', 'FAKENAME', 'FAKEPASSWORD')
@@ -51,7 +51,7 @@ def test_file_upload_70a(tmpdir):
5151
assert 10*'a' == lchunk
5252

5353

54-
def test_ISO_extension(tmpdir):
54+
def test_ISO_extension(tmpdir, fakeicontrolsession):
5555
filepath = tmpdir.mkdir('testdir').join('wrongname.iso')
5656
filepath.write('fake')
5757
mr = ManagementRoot('FAKENETLOC', 'FAKENAME', 'FAKEPASSWORD')
@@ -61,7 +61,7 @@ def test_ISO_extension(tmpdir):
6161
assert EIO.value.message == 'wrongname.iso'
6262

6363

64-
def test_stringio_upload_80a(tmpdir):
64+
def test_stringio_upload_80a(tmpdir, fakeicontrolsession):
6565
sio = StringIO(80*'a')
6666
mr = ManagementRoot('FAKENETLOC', 'FAKENAME', 'FAKEPASSWORD')
6767
mr._meta_data['icr_session'] = mock.MagicMock()
@@ -73,7 +73,7 @@ def test_stringio_upload_80a(tmpdir):
7373
assert d == 'aaaaaaaaaaaaaaaaaaaa'
7474

7575

76-
def test_stringio_upload_70a(tmpdir):
76+
def test_stringio_upload_70a(tmpdir, fakeicontrolsession):
7777
sio = StringIO(70*'a')
7878
mr = ManagementRoot('FAKENETLOC', 'FAKENAME', 'FAKEPASSWORD')
7979
mr._meta_data['icr_session'] = mock.MagicMock()
@@ -87,7 +87,7 @@ def test_stringio_upload_70a(tmpdir):
8787
assert 10*'a' == lchunk
8888

8989

90-
def test_bytes_upload_80a(tmpdir):
90+
def test_bytes_upload_80a(tmpdir, fakeicontrolsession):
9191
bytestring80a = 80*'a'
9292
mr = ManagementRoot('FAKENETLOC', 'FAKENAME', 'FAKEPASSWORD')
9393
mr._meta_data['icr_session'] = mock.MagicMock()
@@ -99,7 +99,7 @@ def test_bytes_upload_80a(tmpdir):
9999
assert d == 'aaaaaaaaaaaaaaaaaaaa'
100100

101101

102-
def test_bytes_upload_70a(tmpdir):
102+
def test_bytes_upload_70a(tmpdir, fakeicontrolsession):
103103
bytestring70a = 70*'a'
104104
mr = ManagementRoot('FAKENETLOC', 'FAKENAME', 'FAKEPASSWORD')
105105
mr._meta_data['icr_session'] = mock.MagicMock()

f5/bigip/test/test___init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@
2626

2727

2828
@pytest.fixture
29-
def FakeBigIP():
29+
def FakeBigIP(fakeicontrolsession):
3030
FBIP = BigIP('FakeHostName', 'admin', 'admin')
3131
FBIP.icontrol = mock.MagicMock()
3232
return FBIP
3333

3434

3535
@pytest.fixture
36-
def FakeBigIPWithPort():
36+
def FakeBigIPWithPort(fakeicontrolsession):
3737
FBIP = BigIP('FakeHostName', 'admin', 'admin', port='10443')
3838
FBIP.icontrol = mock.MagicMock()
3939
return FBIP

f5/bigip/tm/auth/test/test_user.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def FakeUser():
2929

3030

3131
class TestCreate(object):
32-
def test_create_two(self):
32+
def test_create_two(self, fakeicontrolsession):
3333
b = BigIP('localhost', 'admin', 'admin')
3434
n1 = b.auth.users.user
3535
n2 = b.auth.users.user

f5/bigip/tm/cm/test/test___init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121

2222
@pytest.fixture
23-
def FakeiControl():
23+
def FakeiControl(fakeicontrolsession):
2424
bigip = BigIP('host', 'fake_admin', 'fake_admin')
2525
mock_session = mock.MagicMock()
2626
mock_session.post.return_value.json.return_value = {}

f5/bigip/tm/cm/trust.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def __init__(self, cm):
3838
self._meta_data['required_json_kind'] = \
3939
'tm:cm:add-to-trust:runstate'
4040
self._meta_data['allowed_commands'].append('run')
41+
self._meta_data['supported_versions'].discard('11.6.0')
4142

4243

4344
class Remove_From_Trust(UnnamedResourceMixin, CommandExecutionMixin, Resource):
@@ -59,3 +60,4 @@ def __init__(self, cm):
5960
self._meta_data['required_json_kind'] = \
6061
'tm:cm:remove-from-trust:runstate'
6162
self._meta_data['allowed_commands'].append('run')
63+
self._meta_data['supported_versions'].discard('11.6.0')

0 commit comments

Comments
 (0)