Skip to content

Commit c723347

Browse files
authored
Merge branch 'develop' into tests_and_docstring_for_post_body
2 parents fdff4a6 + 027e761 commit c723347

16 files changed

+164
-125
lines changed

.travis.yml

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,12 @@ before_install:
1212
- echo password=changed! >> $HOME/.splunkrc
1313
# Set SPLUNK_HOME
1414
- export SPLUNK_HOME="/opt/splunk"
15-
# Pull docker image
16-
- docker pull splunk/splunk-sdk-travis-ci:$SPLUNK_VERSION
1715
# Add DOCKER to iptables, 1/10 times this is needed, force 0 exit status
1816
- sudo iptables -N DOCKER || true
19-
# Start Docker container
20-
- docker run -p 127.0.0.1:8089:8089 -d splunk/splunk-sdk-travis-ci:$SPLUNK_VERSION
21-
# curl Splunk until it returns valid data indicating it has been setup, try 20 times maximum
22-
- for i in `seq 0 20`; do if curl --fail -k https://localhost:8089/services/server/info &> /dev/null; then break; fi; echo $i; sleep 1; done
17+
# Start docker-compose in detached mode
18+
- docker-compose up -d
19+
# Health Check (3 minutes)
20+
- for i in `seq 0 180`; do if docker exec -it splunk /sbin/checkstate.sh &> /dev/null; then break; fi; echo $i; sleep 1; done
2321
# The upload test needs to refer to a file that Splunk has in the docker
2422
# container
2523
- export INPUT_EXAMPLE_UPLOAD=$SPLUNK_HOME/var/log/splunk/splunkd_ui_access.log
@@ -32,8 +30,8 @@ before_install:
3230
language: python
3331

3432
env:
35-
- SPLUNK_VERSION=7.3-sdk
36-
- SPLUNK_VERSION=8.0-sdk
33+
- SPLUNK_VERSION=7.3
34+
- SPLUNK_VERSION=8.0
3735

3836
python:
3937
- "2.7"

README.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ The Splunk platform is popular with system administrators for aggregation and mo
1313

1414
The Splunk developer platform enables developers to take advantage of the same technology used by the Splunk platform to build exciting new applications.
1515

16-
For more information, see [Splunk Enterprise SDK for Python](https://dev.splunk.com/enterprise/docs/devtools/python/sdk-python/) on the Splunk Developer Portal.
16+
## Getting started with the Splunk SDK for Python
1717

1818

1919
## Get started with the Splunk Enterprise SDK for Python
@@ -37,7 +37,6 @@ Here's what you need to get going with the Splunk Enterprise SDK for Python.
3737

3838
Get the Splunk Enterprise SDK for Python from [PyPI](https://pypi.org/project/splunk-sdk/). If you want to contribute to the SDK, clone the repository from [GitHub](https://github.com/splunk/splunk-sdk-python).
3939

40-
4140
### Install the SDK
4241

4342
Use the following commands to install the Splunk Enterprise SDK for Python libraries in different ways. However, it's not necessary to install the libraries to run the examples and unit tests from the SDK.
@@ -58,8 +57,17 @@ Install the sources you cloned from GitHub:
5857

5958
[sudo] python setup.py install
6059

60+
## Testing Quickstart
61+
62+
You'll need `docker` and `docker-compose` to get up and running using this method.
6163

62-
### Run the examples and unit tests
64+
```
65+
make up SPLUNK_VERSION=8.0
66+
make wait_up
67+
make splunkrc_default
68+
make test
69+
make down
70+
```
6371

6472
To run the examples and unit tests, you must put the root of the SDK on your PYTHONPATH. For example, if you downloaded the SDK to your home folder and are running OS X or Linux, add the following line to your **.bash_profile** file:
6573

docker-compose.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
version: '3.6'
2+
3+
services:
4+
splunk:
5+
image: "splunk/splunk:${SPLUNK_VERSION}"
6+
container_name: splunk
7+
environment:
8+
- SPLUNK_START_ARGS=--accept-license
9+
- SPLUNK_HEC_TOKEN=11111111-1111-1111-1111-1111111111113
10+
- SPLUNK_PASSWORD=changed!
11+
- SPLUNK_APPS_URL=https://github.com/splunk/sdk-app-collection/releases/download/v1.0.0/sdk-app-collection.tgz
12+
ports:
13+
- 8000:8000
14+
- 8088:8088
15+
- 8089:8089
16+
healthcheck:
17+
test: ['CMD', 'curl', '-f', 'http://localhost:8000']
18+
interval: 5s
19+
timeout: 5s
20+
retries: 20

docs/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343

4444
# General information about the project.
4545
project = u'Splunk SDK for Python'
46-
copyright = u'2014, Splunk Inc'
46+
copyright = u'2020, Splunk Inc'
4747

4848
# The version info for the project you're documenting, acts as replacement for
4949
# |version| and |release|, also used in various other places throughout the
@@ -95,7 +95,7 @@
9595
# a list of builtin themes.
9696

9797
# agogo, default, epub, haiku, nature, pyramid, scrolls, sphinxdoc, traditional
98-
html_theme = 'default'
98+
html_theme = 'default'
9999

100100
# Theme options are theme-specific and customize the look and feel of a theme
101101
# further. For a list of options available for each theme, see the

scripts/build-splunkrc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
'host': 'localhost',
2626
'port': '8089',
2727
'username': 'admin',
28-
'password': 'changeme',
28+
'password': 'changed!',
2929
'scheme': 'https',
30-
'version': '6.3'
30+
'version': '8.0'
3131
}
3232

3333
DEFAULT_SPLUNKRC_PATH = os.path.join(str(Path.home()), '.splunkrc')

splunklib/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1872,7 +1872,7 @@ def delete(self, username, realm=None):
18721872
name = UrlEncoded(realm, encode_slash=True) + ":" + UrlEncoded(username, encode_slash=True)
18731873

18741874
# Append the : expected at the end of the name
1875-
if name[-1] is not ":":
1875+
if name[-1] != ":":
18761876
name = name + ":"
18771877
return Collection.delete(self, name)
18781878

splunklib/searchcommands/generating_command.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -204,19 +204,21 @@ def _execute(self, ifile, process):
204204
205205
"""
206206
if self._protocol_version == 2:
207-
result = self._read_chunk(self._as_binary_stream(ifile))
207+
self._execute_v2(ifile, self.generate())
208+
else:
209+
assert self._protocol_version == 1
210+
self._record_writer.write_records(self.generate())
211+
self.finish()
208212

209-
if not result:
213+
def _execute_chunk_v2(self, process, chunk):
214+
count = 0
215+
for row in process:
216+
self._record_writer.write_record(row)
217+
count += 1
218+
if count == self._record_writer._maxresultrows:
219+
self._finished = False
210220
return
211-
212-
metadata, body = result
213-
action = getattr(metadata, 'action', None)
214-
215-
if action != 'execute':
216-
raise RuntimeError('Expected execute action, not {}'.format(action))
217-
218-
self._record_writer.write_records(self.generate())
219-
self.finish()
221+
self._finished = True
220222

221223
# endregion
222224

splunklib/searchcommands/internals.py

Lines changed: 63 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import os
3636
import re
3737
import sys
38+
import warnings
3839

3940
from . import environment
4041

@@ -74,7 +75,7 @@ def set_binary_mode(fh):
7475

7576

7677
class CommandLineParser(object):
77-
""" Parses the arguments to a search command.
78+
r""" Parses the arguments to a search command.
7879
7980
A search command line is described by the following syntax.
8081
@@ -505,8 +506,8 @@ def __init__(self, ofile, maxresultrows=None):
505506

506507
self._inspector = OrderedDict()
507508
self._chunk_count = 0
508-
self._record_count = 0
509-
self._total_record_count = 0
509+
self._pending_record_count = 0
510+
self._committed_record_count = 0
510511

511512
@property
512513
def is_flushed(self):
@@ -524,6 +525,30 @@ def ofile(self):
524525
def ofile(self, value):
525526
self._ofile = set_binary_mode(value)
526527

528+
@property
529+
def pending_record_count(self):
530+
return self._pending_record_count
531+
532+
@property
533+
def _record_count(self):
534+
warnings.warn(
535+
"_record_count will be deprecated soon. Use pending_record_count instead.",
536+
PendingDeprecationWarning
537+
)
538+
return self.pending_record_count
539+
540+
@property
541+
def committed_record_count(self):
542+
return self._committed_record_count
543+
544+
@property
545+
def _total_record_count(self):
546+
warnings.warn(
547+
"_total_record_count will be deprecated soon. Use committed_record_count instead.",
548+
PendingDeprecationWarning
549+
)
550+
return self.committed_record_count
551+
527552
def write(self, data):
528553
bytes_type = bytes if sys.version_info >= (3, 0) else str
529554
if not isinstance(data, bytes_type):
@@ -555,8 +580,7 @@ def _clear(self):
555580
self._buffer.seek(0)
556581
self._buffer.truncate()
557582
self._inspector.clear()
558-
self._record_count = 0
559-
self._flushed = False
583+
self._pending_record_count = 0
560584

561585
def _ensure_validity(self):
562586
if self._finished is True:
@@ -651,9 +675,9 @@ def _write_record(self, record):
651675
values += (repr(value), None)
652676

653677
self._writerow(values)
654-
self._record_count += 1
678+
self._pending_record_count += 1
655679

656-
if self._record_count >= self._maxresultrows:
680+
if self.pending_record_count >= self._maxresultrows:
657681
self.flush(partial=True)
658682

659683
try:
@@ -690,7 +714,7 @@ def flush(self, finished=None, partial=None):
690714

691715
RecordWriter.flush(self, finished, partial) # validates arguments and the state of this instance
692716

693-
if self._record_count > 0 or (self._chunk_count == 0 and 'messages' in self._inspector):
717+
if self.pending_record_count > 0 or (self._chunk_count == 0 and 'messages' in self._inspector):
694718

695719
messages = self._inspector.get('messages')
696720

@@ -728,9 +752,9 @@ def flush(self, finished=None, partial=None):
728752
print(level, text, file=stderr)
729753

730754
self.write(self._buffer.getvalue())
731-
self._clear()
732755
self._chunk_count += 1
733-
self._total_record_count += self._record_count
756+
self._committed_record_count += self.pending_record_count
757+
self._clear()
734758

735759
self._finished = finished is True
736760

@@ -748,37 +772,36 @@ class RecordWriterV2(RecordWriter):
748772
def flush(self, finished=None, partial=None):
749773

750774
RecordWriter.flush(self, finished, partial) # validates arguments and the state of this instance
751-
inspector = self._inspector
752-
753-
if self._flushed is False:
754-
755-
self._total_record_count += self._record_count
756-
self._chunk_count += 1
757-
758-
# TODO: DVPL-6448: splunklib.searchcommands | Add support for partial: true when it is implemented in
759-
# ChunkedExternProcessor (See SPL-103525)
760-
#
761-
# We will need to replace the following block of code with this block:
762-
#
763-
# metadata = [
764-
# ('inspector', self._inspector if len(self._inspector) else None),
765-
# ('finished', finished),
766-
# ('partial', partial)]
767-
768-
if len(inspector) == 0:
769-
inspector = None
770-
771-
if partial is True:
772-
finished = False
773775

774-
metadata = [item for item in (('inspector', inspector), ('finished', finished))]
775-
self._write_chunk(metadata, self._buffer.getvalue())
776-
self._clear()
776+
if partial or not finished:
777+
# Don't flush partial chunks, since the SCP v2 protocol does not
778+
# provide a way to send partial chunks yet.
779+
return
777780

778-
elif finished is True:
779-
self._write_chunk((('finished', True),), '')
781+
if not self.is_flushed:
782+
self.write_chunk(finished=True)
780783

781-
self._finished = finished is True
784+
def write_chunk(self, finished=None):
785+
inspector = self._inspector
786+
self._committed_record_count += self.pending_record_count
787+
self._chunk_count += 1
788+
789+
# TODO: DVPL-6448: splunklib.searchcommands | Add support for partial: true when it is implemented in
790+
# ChunkedExternProcessor (See SPL-103525)
791+
#
792+
# We will need to replace the following block of code with this block:
793+
#
794+
# metadata = [item for item in (('inspector', inspector), ('finished', finished), ('partial', partial))]
795+
#
796+
# if partial is True:
797+
# finished = False
798+
799+
if len(inspector) == 0:
800+
inspector = None
801+
802+
metadata = [item for item in (('inspector', inspector), ('finished', finished))]
803+
self._write_chunk(metadata, self._buffer.getvalue())
804+
self._clear()
782805

783806
def write_metadata(self, configuration):
784807
self._ensure_validity()
@@ -793,7 +816,7 @@ def write_metric(self, name, value):
793816
self._inspector['metric.' + name] = value
794817

795818
def _clear(self):
796-
RecordWriter._clear(self)
819+
super(RecordWriterV2, self)._clear()
797820
self._fieldnames = None
798821

799822
def _write_chunk(self, metadata, body):
@@ -818,4 +841,4 @@ def _write_chunk(self, metadata, body):
818841
self.write(metadata)
819842
self.write(body)
820843
self._ofile.flush()
821-
self._flushed = False
844+
self._flushed = True

0 commit comments

Comments
 (0)