Skip to content
Closed
12 changes: 12 additions & 0 deletions tests/smoke/test_ucc_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ def test_ucc_generate_with_everything(caplog):
("default", "splunk_ta_uccexample_settings.conf"),
("default", "web.conf"),
("default", "server.conf"),
("default", "commands.conf"),
("default", "searchbnf.conf"),
("default", "data", "ui", "alerts", "test_alert.html"),
("default", "data", "ui", "nav", "default.xml"),
("default", "data", "ui", "views", "configuration.xml"),
Expand All @@ -166,6 +168,16 @@ def test_ucc_generate_with_everything(caplog):
("bin", "example_input_three.py"),
("bin", "example_input_four.py"),
("bin", "import_declare_test.py"),
("bin", "countmatchescommand.py"),
("bin", "countmatches.py"),
("bin", "filter.py"),
("bin", "filtercommand.py"),
("bin", "generatetext.py"),
("bin", "generatetextcommand.py"),
("bin", "sumcommand.py"),
("bin", "sum.py"),
("bin", "sum_without_map.py"),
("bin", "sumtwocommand.py"),
("bin", "splunk_ta_uccexample_rh_account.py"),
("bin", "splunk_ta_uccexample_rh_example_input_one.py"),
("bin", "splunk_ta_uccexample_rh_example_input_two.py"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ check_requires_access_to_files_outside_apps_dir:
comment: 'Y'
check_for_secret_disclosure:
comment: 'Y'
check_custom_commands:
comment: "The custom command is only for testing purpose, the add-on won't be released."
Original file line number Diff line number Diff line change
Expand Up @@ -1034,5 +1034,106 @@
"version": "5.5.8+5fd76615",
"displayName": "Splunk UCC test Add-on",
"schemaVersion": "0.0.2"
}
},
"customSearchCommand": [
{
"commandName": "generatetextcommand",
"fileName": "generatetext.py",
"commandType": "generating",
"requiredSearchAssistant": true,
"description": " This command generates COUNT occurrences of a TEXT string.",
"syntax": "generatetextcommand count=<event_count> text=<string>",
"usage": "public",
"arguments": [
{
"name": "count",
"required": true,
"validate": {
"type": "Integer",
"minimum": 5,
"maximum": 10
}
},
{
"name": "text",
"required": true
}
]
},
{
"commandName": "filtercommand",
"fileName": "filter.py",
"commandType": "dataset processing",
"requiredSearchAssistant": true,
"description": "It filters records from the events stream returning only those which has :code:`contains` in them and replaces :code:`replace_array[0]` with :code:`replace_array[1]`.",
"syntax": "| filtercommand contains='value1' replace='value to be replaced,value to replace with'",
"usage": "public",
"arguments": [
{
"name": "contains"
},
{
"name": "replace_array"
}
]
},
{
"commandName": "sumcommand",
"fileName": "sum.py",
"commandType": "transforming",
"requiredSearchAssistant": true,
"description": "The total produced is sum(sum(fieldname, 1, n), 1, N) where n = number of fields, N = number of records.",
"syntax": "| sumcommand total=lines linecount",
"usage": "public",
"arguments": [
{
"name": "total",
"validate": {
"type": "Fieldname"
},
"required": true
}
]
},
{
"commandName": "sumtwocommand",
"fileName": "sum_without_map.py",
"commandType": "transforming",
"requiredSearchAssistant": true,
"description": "The total produced is sum(sum(fieldname, 1, n), 1, N) where n = number of fields, N = number of records.",
"syntax": "| sumtwocommand total=lines linecount",
"usage": "public",
"arguments": [
{
"name": "total",
"validate": {
"type": "Fieldname"
},
"required": true
}
]
},
{
"commandName": "countmatchescommand",
"fileName": "countmatches.py",
"commandType": "streaming",
"requiredSearchAssistant": false,
"arguments": [
{
"name": "fieldname",
"validate": {
"type": "Fieldname"
},
"required": true
},
{
"name": "pattern",
"validate": {
"type": "RegularExpression"
},
"required": true
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def stream(self, records):
for record in records:
# write custom logic for the search command
yield record
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import sys
import import_declare_test

from splunklib.searchcommands import \
dispatch, StreamingCommand, Configuration, Option, validators
from countmatches import stream

@Configuration()
class CountmatchescommandCommand(StreamingCommand):

fieldname = Option(name='fieldname', require=True, validate=validators.Fieldname())
pattern = Option(name='pattern', require=True, validate=validators.RegularExpression())

def stream(self, events):
return stream(self, events)

dispatch(CountmatchescommandCommand, sys.argv, sys.stdin, sys.stdout, __name__)
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
def transform(self, records):
contains = self.contains
replace_array = self.replace_array

if contains and replace_array:
arr = replace_array.split(",")
if len(arr) != 2:
raise ValueError("Please provide only two arguments, separated by comma for 'replace'")

for record in records:
_raw = record.get("_raw")
if contains in _raw:
record["_raw"] = _raw.replace(arr[0], arr[1])
yield record
return

if contains:
for record in records:
_raw = record.get("_raw")
if contains in _raw:
yield record
return

if replace_array:
arr = replace_array.split(",")
if len(arr) != 2:
raise ValueError("Please provide only two arguments, separated by comma for 'replace'")

for record in records:
_raw = record.get("_raw")
record["_raw"] = _raw.replace(arr[0], arr[1])
yield record
return

for record in records:
yield record
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import sys
import import_declare_test

from splunklib.searchcommands import \
dispatch, EventingCommand, Configuration, Option, validators
from filter import transform

@Configuration()
class FiltercommandCommand(EventingCommand):
"""

##Syntax
| filtercommand contains='value1' replace='value to be replaced,value to replace with'

##Description
It filters records from the events stream returning only those which has :code:`contains` in them and replaces :code:`replace_array[0]` with :code:`replace_array[1]`.

"""

contains = Option(name='contains', require=False)
replace_array = Option(name='replace_array', require=False)

def transform(self, events):
return transform(self, events)

dispatch(FiltercommandCommand, sys.argv, sys.stdin, sys.stdout, __name__)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import time
import logging


def generate(self):
logging.debug("Generating %d events with text %s" % (self.count, self.text))
for i in range(1, self.count + 1):
yield {'_serial': i, '_time': time.time(), '_raw': str(i) + '. ' + self.text}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import sys
import import_declare_test

from splunklib.searchcommands import \
dispatch, GeneratingCommand, Configuration, Option, validators
from generatetext import generate

@Configuration()
class GeneratetextcommandCommand(GeneratingCommand):
"""

##Syntax
generatetextcommand count=<event_count> text=<string>

##Description
This command generates COUNT occurrences of a TEXT string.

"""
count = Option(name='count', require=True, validate=validators.Integer(minimum=5, maximum=10))
text = Option(name='text', require=True)

def generate(self):
return generate(self)

dispatch(GeneratetextcommandCommand, sys.argv, sys.stdin, sys.stdout, __name__)
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import logging

def map(self, records):
""" Computes sum(fieldname, 1, n) and stores the result in 'total' """
fieldnames = self.fieldnames
total = 0.0
for record in records:
for fieldname in fieldnames:
total += float(record[fieldname])
yield {self.total: total}

def reduce(self, records):
""" Computes sum(total, 1, N) and stores the result in 'total' """
fieldname = self.total
total = 0.0
for record in records:
value = record[fieldname]
try:
total += float(value)
except ValueError:
logging.debug(' could not convert %s value to float: %s', fieldname, repr(value))
yield {self.total: total}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import logging

def reduce(self, records):
""" Computes sum(total, 1, N) and stores the result in 'total' """
fieldname = self.total
total = 0.0
for record in records:
value = record[fieldname]
try:
total += float(value)
except ValueError:
logging.debug(' could not convert %s value to float: %s', fieldname, repr(value))
yield {self.total: total}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import sys
import import_declare_test

from splunklib.searchcommands import \
dispatch, ReportingCommand, Configuration, Option, validators

from sum import reduce

try:
from sum import map as module_map
except ImportError:
module_map = None

@Configuration()
class SumcommandCommand(ReportingCommand):
"""

##Syntax
| sumcommand total=lines linecount

##Description
The total produced is sum(sum(fieldname, 1, n), 1, N) where n = number of fields, N = number of records.

"""

total = Option(name='total', require=True, validate=validators.Fieldname())

if module_map is not None:
@Configuration()
def map(self, events):
return module_map(self, events)

def reduce(self, events):
return reduce(self, events)

dispatch(SumcommandCommand, sys.argv, sys.stdin, sys.stdout, __name__)
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import sys
import import_declare_test

from splunklib.searchcommands import \
dispatch, ReportingCommand, Configuration, Option, validators

from sum_without_map import reduce

try:
from sum_without_map import map as module_map
except ImportError:
module_map = None

@Configuration()
class SumtwocommandCommand(ReportingCommand):
"""

##Syntax
| sumtwocommand total=lines linecount

##Description
The total produced is sum(sum(fieldname, 1, n), 1, N) where n = number of fields, N = number of records.

"""

total = Option(name='total', require=True, validate=validators.Fieldname())

if module_map is not None:
@Configuration()
def map(self, events):
return module_map(self, events)

def reduce(self, events):
return reduce(self, events)

dispatch(SumtwocommandCommand, sys.argv, sys.stdin, sys.stdout, __name__)
Loading