Skip to content

Commit 9c6c51a

Browse files
author
Frederick Ross
committed
Resolve review comments from David.
Rewrote Input.update more cleanly. Edited Inputs.create to handle tcp/udp case more cleanly. Added escape from a test on 4.x that requires 5.0 to run. Made searching for an unused port in input tests smarter in a couple cases.
1 parent 30bbe79 commit 9c6c51a

File tree

2 files changed

+73
-26
lines changed

2 files changed

+73
-26
lines changed

splunklib/client.py

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1670,7 +1670,7 @@ def __init__(self, service, path, kind=None, **kwargs):
16701670
Entity.__init__(self, service, path, **kwargs)
16711671
if kind is None:
16721672
path_segments = path.split('/')
1673-
i = path_segments.index('inputs')+1
1673+
i = path_segments.index('inputs') + 1
16741674
if path_segments[i] == 'tcp':
16751675
self.kind = path_segments[i] + '/' + path_segments[i+1]
16761676
else:
@@ -1684,28 +1684,49 @@ def __init__(self, service, path, kind=None, **kwargs):
16841684
if self.kind == 'splunktcp':
16851685
self.kind = 'tcp/cooked'
16861686

1687+
@property
1688+
def restrictToHost(self):
1689+
if 'restrictToHost' in self._state.content:
1690+
return self._state.content['restrictToHost']
1691+
else:
1692+
return ''
1693+
16871694
def update(self, **kwargs):
16881695
if self.kind not in ['tcp', 'splunktcp', 'tcp/raw', 'tcp/cooked']:
16891696
result = super(Input, self).update(**kwargs)
16901697
return result
1691-
elif 'restrictToHost' in kwargs and self.service.splunk_version < (5,):
1692-
raise IllegalOperationException("Updating restrictToHost has no effect before Splunk 5.0")
16931698
else:
1699+
# TCP inputs have a property 'restrictToHost' which requires special care.
1700+
1701+
# There is a bug in Splunk < 5.0. Don't bother trying to update restrictToHost.
1702+
if 'restrictToHost' in kwargs and self.service.splunk_version < (5,):
1703+
raise IllegalOperationException("Updating restrictToHost has no effect before Splunk 5.0")
1704+
1705+
# In Splunk 4.x, if you update without restrictToHost as one of the fields,
1706+
# restrictToHost keeps its previous state. In 5.0, it is set to empty string.
1707+
# Thus, we must pass it every time. This doesn't actually introduce a race
1708+
# condition because if someone else has set restrictToHost to a new value on this
1709+
# TCP input, our update request will fail, since our reference to it still uses
1710+
# the old path.
1711+
to_update = kwargs.copy()
1712+
to_update['restrictToHost'] = kwargs.get('restrictToHost', self['restrictToHost'])
1713+
1714+
# Do the actual update operation.
1715+
result = super(Input, self).update(**to_update)
1716+
1717+
# Now we must update the path in case it changed.
1718+
# The pieces we break it into are:
1719+
# https://localhost:8089/services/data/inputs/tcp/raw/ boris: 10000
1720+
# |------------------ base_path -----------------------| | host || port|
1721+
assert self.path.endswith('/')
1722+
base_path = self.path.rsplit('/', 2)[0]
1723+
host = to_update['restrictToHost'] + ':' if to_update['restrictToHost'] != '' else ''
16941724
port = self.name.split(':', 1)[-1]
1695-
new_kwargs = kwargs.copy()
1696-
if 'restrictToHost' not in new_kwargs and ':' in self.name:
1697-
new_kwargs['restrictToHost'] = self['restrictToHost']
1698-
result = super(Input, self).update(**new_kwargs)
1699-
if self.path.endswith('/'):
1700-
base_path, name = self.path.rsplit('/', 2)[:-1]
1701-
else:
1702-
base_path, name = self.path.rsplit('/', 1)
1703-
if 'restrictToHost' in new_kwargs and new_kwargs['restrictToHost'] != '':
1704-
self.path = base_path + '/' + new_kwargs['restrictToHost'] + ':' + port
1705-
else:
1706-
self.path = base_path + '/' + port
1725+
self.path = base_path + '/' + host + port
1726+
17071727
return result
17081728

1729+
17091730
# Inputs is a "kinded" collection, which is a heterogenous collection where
17101731
# each item is tagged with a kind, that provides a single merged view of all
17111732
# input kinds.
@@ -1803,15 +1824,16 @@ def create(self, kind, name, **kwargs):
18031824
:return: The new input.
18041825
"""
18051826
kindpath = self.kindpath(kind)
1806-
if (kindpath == 'tcp/raw' or kindpath == 'tcp/cooked' or kindpath == 'udp') and \
1807-
'restrictToHost' in kwargs:
1808-
post_name = name
1809-
path_name = kwargs['restrictToHost'] + ':' + name
1810-
else:
1811-
post_name = name
1812-
path_name = name
1813-
self.post(kindpath, name=post_name, **kwargs)
1814-
path = _path(self.path + kindpath, path_name)
1827+
self.post(kindpath, name=name, **kwargs)
1828+
1829+
# If we created an input with restrictToHost set, then
1830+
# its path will be <restrictToHost>:<name>, not just <name>,
1831+
# and we have to adjust accordingly.
1832+
path = _path(
1833+
self.path + kindpath,
1834+
'%s:%s' % (kwargs['restrictToHost'], name) \
1835+
if kwargs.has_key('restrictToHost') else name
1836+
)
18151837
return Input(self.service, path, kind)
18161838

18171839
def delete(self, kind, name=None):

tests/test_input.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ def test_cannot_create_with_restrictToHost_in_name(self):
5252
)
5353

5454
def test_remove_host_restriction(self):
55+
if self.service.splunk_version < (5,):
56+
# We can't set restrictToHost before 5.0 due to a bug in splunkd.
57+
return
5558
input = self.service.inputs.create('tcp', str(self.base_port), restrictToHost='boris')
5659
input.update(restrictToHost='')
5760
input.refresh()
@@ -91,12 +94,26 @@ def test_unrestricted_to_restricted_collision(self):
9194

9295
def test_update_restrictToHost(self):
9396
for kind in ['tcp', 'splunktcp']:
94-
boris = self.service.inputs.create(kind, str(self.base_port), restrictToHost='boris')
97+
port = self.base_port
98+
while True: # Find the next unbound port
99+
try:
100+
boris = self.service.inputs.create(kind, str(port), restrictToHost='boris')
101+
except client.HTTPError as he:
102+
if he.status == 400:
103+
port += 1
104+
else:
105+
break
106+
107+
# No matter what version we're actually running against,
108+
# we can check that on Splunk < 5.0, we get an exception
109+
# from trying to update restrictToHost.
95110
with self.fake_splunk_version((4,3)):
96111
self.assertRaises(
97112
client.IllegalOperationException,
98113
lambda: boris.update(restrictToHost='hilda')
99114
)
115+
116+
# And now back to real tests...
100117
if self.service.splunk_version >= (5,):
101118
boris.update(restrictToHost='hilda')
102119
boris.refresh()
@@ -107,7 +124,15 @@ def test_update_restrictToHost(self):
107124

108125
def test_update_nonrestrictToHost(self):
109126
for kind in ['tcp', 'splunktcp']:
110-
input = self.service.inputs.create(kind, str(self.base_port), restrictToHost='boris')
127+
port = self.base_port
128+
while True: # Find the next unbound port
129+
try:
130+
input = self.service.inputs.create(kind, str(port), restrictToHost='boris')
131+
except client.HTTPError as he:
132+
if he.status == 400:
133+
port += 1
134+
else:
135+
break
111136
try:
112137
input.update(host='meep')
113138
input.refresh()

0 commit comments

Comments
 (0)