示例#1
0
    def test_empty_stanzas(self):
        """ Comparison should detect the different between empty and missing stanzas."""
        a = parse_string("""
        [common]
        a = 1
        b = 2

        [in_a1]
        live_in = a

        [in_a_only]
        """)
        b = parse_string("""
        [common]
        b = 2
        a = 1

        [in_b1]
        live_in = b

        [in_b_only]
        """)
        delta = compare_cfgs(a, b)
        delta_search = partial(self.find_op_by_location, delta)
        self.assertEqual(delta_search("stanza", stanza="common").tag, DIFF_OP_EQUAL)
        self.assertEqual(delta_search("stanza", stanza="in_a_only").tag, DIFF_OP_DELETE)
        self.assertEqual(delta_search("stanza", stanza="in_b_only").tag, DIFF_OP_INSERT)

        op = delta_search("stanza", stanza="in_b1")
        self.assertEqual(op.tag, DIFF_OP_INSERT)
        self.assertEqual(op.b["live_in"], "b")

        op = delta_search("stanza", stanza="in_a1")
        self.assertEqual(op.tag, DIFF_OP_DELETE)
        self.assertEqual(op.a["live_in"], "a")
示例#2
0
    def test_attribute_replace(self):
        props1 = parse_string(r"""
        [dhcp]
        EVAL-lease_end = lease_start+lease_duration
        EXTRACT-loglevel = ^\d+ (?<log_level>[^ ]+)
        EXTRACT-report-ack = ACK (?<dest_ip>[0-9.]+)/\d+ for (?<lease_duration>\d+)
        """)

        props2 = parse_string(r"""
        [dhcp]
        EVAL-lease_end = lease_start + lease_duration
        EXTRACT-loglevel = ^\d+ (?<log_level>[^ ]+)
        # Support IPv6
        EXTRACT-report-ack = ACK (?<dest_ip>[0-9A-Fa-f.:]+)/\d+ for (?<lease_duration>\d+)
        """)

        delta = compare_cfgs(props1, props2)
        delta_search = partial(self.find_op_by_location, delta)
        self.assertEqual(delta_search("key", stanza="dhcp", key="EXTRACT-loglevel").tag, DIFF_OP_EQUAL)

        lease_end = delta_search("key", stanza="dhcp", key="EVAL-lease_end")
        self.assertEqual(lease_end.tag, DIFF_OP_REPLACE)
        self.assertEqual(lease_end.a, "lease_start+lease_duration")
        self.assertEqual(lease_end.b, "lease_start + lease_duration")

        reportack = delta_search("key", stanza="dhcp", key="EXTRACT-report-ack")
        self.assertEqual(reportack.tag, DIFF_OP_REPLACE)
        self.assertIn(r"(?<dest_ip>[0-9A-Fa-f.:]+)", reportack.b)
        self.assertNotIn(r"(?<dest_ip>[0-9A-Fa-f.:]+)", reportack.a)
示例#3
0
    def test_dup_stanzas(self):
        t = """
        [jungle]
        animal = monkey
        key2 = 01

        [forest]
        animal = wolf

        [jungle]
        animal = snake
        """
        with self.assertRaises(DuplicateStanzaException):
            parse_string(t, dup_stanza=DUP_EXCEPTION)

        c = parse_string(t, dup_stanza=DUP_MERGE)
        self.assertEqual(c["jungle"]["animal"], "snake")
        self.assertEqual(c["jungle"]["key2"], "01")
        self.assertEqual(c["forest"]["animal"], "wolf")

        c = parse_string(t, dup_stanza=DUP_OVERWRITE)
        self.assertEqual(c["jungle"]["animal"], "snake")
        with self.assertRaises(KeyError):
            c["jungle"]["key2"]
        self.assertEqual(c["forest"]["animal"], "wolf")
示例#4
0
 def test_strict_junk(self):
     t = """
     [stanza]
     key1 = an every-day value
     a random line of text that's not a key/value pair
     key2 = normalness
     """
     with self.assertRaises(ConfParserException):
         parse_string(t, strict=True)
示例#5
0
    def test_dup_keys(self):
        t = """
        [jungle]
        animal = monkey
        animal = snake
        [forest]
        animal = wolf
        """
        with self.assertRaises(DuplicateKeyException):
            parse_string(t, dup_key=DUP_EXCEPTION)

        c = parse_string(t, dup_key=DUP_MERGE)
        self.assertEqual(c["jungle"]["animal"], "snake")
        self.assertEqual(c["forest"]["animal"], "wolf")
示例#6
0
 def test_unused_features(self):
     """ Make coverage stop complaining about stuff we don't use.  Remove later? """
     t = r"""
     [stanza]
     key1 = an every-day value
     KEY2 = normalness \
     another line
     """
     c = parse_string(t, strict=False, keys_lower=True)
     self.assertIn("key2", c["stanza"])
     self.assertEqual(len(c["stanza"]["key2"].split("\n")), 2)
     c = parse_string(t, strict=False, handle_conts=False)
     self.assertEqual(len(c["stanza"]["KEY2"].split("\n")), 1)
     self.assertNotIn("another line", c["stanza"]["KEY2"])
示例#7
0
    def test_imballanced_stanas(self):
        """ Imbalanced stanzas """
        a = parse_string("""
        [s0]
        _ = same
        [s1]
        a = 1
        b = 2
        [s3]
        y = 75
        [s4]
        z = 99
        """)
        b = parse_string("""
        [s0]
        _ = same
        [s1]
        a = 1
        c = 3
        [s2]
        x = 50
        [s4]
        zelda =
        """)
        delta = compare_cfgs(a, b)
        delta_search = partial(self.find_op_by_location, delta)

        op = delta_search("stanza", stanza="s0")
        self.assertEqual(op.tag, DIFF_OP_EQUAL)
        self.assertEqual(op.a, op.b)

        self.assertEqual(
            delta_search("key", stanza="s1", key="a").tag, DIFF_OP_EQUAL)
        self.assertEqual(
            delta_search("key", stanza="s1", key="b").tag, DIFF_OP_DELETE)
        self.assertEqual(
            delta_search("key", stanza="s1", key="c").tag, DIFF_OP_INSERT)

        self.assertEqual(
            delta_search("stanza", stanza="s2").tag, DIFF_OP_INSERT)
        self.assertEqual(
            delta_search("stanza", stanza="s3").tag, DIFF_OP_DELETE)
        self.assertEqual(
            delta_search("stanza", stanza="s4").tag, DIFF_OP_REPLACE)
示例#8
0
 def test_global_stanzs(self):
     c = parse_string("""
     animal = dog
     [jungle]
     animal = monkey
     [forest]
     animal = wolf
     """)  # Trailing white space on key2
     self.assertEqual(c[GLOBAL_STANZA]["animal"], "dog")
     self.assertEqual(c["jungle"]["animal"], "monkey")
     self.assertEqual(c["forest"]["animal"], "wolf")
示例#9
0
 def test_missing_key(self):
     c = parse_string("""\
     [stanza1]
     key1=yes
     =  no
     [stanza2]
       = whoopsie
       """)
     self.assertEqual(c["stanza1"]["key1"], "yes")
     # Todo:  Review if this should throw an error or not...
     self.assertEqual(c["stanza1"][""], "no")
     self.assertEqual(c["stanza2"][""], "whoopsie")
示例#10
0
 def test_preserve_empty_stanza_bug77(self):
     c = parse_string("""
     [capability::db_connect_create_connection]
     [capability::db_connect_read_connection]
     [capability::db_connect_update_connection]
     [capability::db_connect_delete_connection]
     """)
     self.assertTrue("capability::db_connect_create_connection" in c,
                     "Must preserve empty stanza")
     self.assertTrue("capability::db_connect_delete_connection" in c,
                     "Must preserve empty stanza")
     self.assertEqual(len(c), 4)
示例#11
0
 def test_splksysdfltjunk(self):
     # This is copied from Splunk's system/default/props.conf file.  (We are CERTAINLY more
     # picky than splunk when it comes to parsing these files.
     # Whoops, semi-colons aren't comments!
     t = """
     [sar]
     ; break on blanklines, clock-resets, or common headers attributes (/s, %, or alpha-)
     BREAK_ONLY_BEFORE = (?:^\s*$)|00:00:0|/s|%|[a-z]-
     MAX_EVENTS = 1000
     """
     c = parse_string(t, profile=PARSECONF_MID)
     self.assertEqual(c["sar"]["MAX_EVENTS"], "1000")
示例#12
0
    def test_bad_stanza(self):
        t1 = """
        [Errors in the last hour
        search = error OR failed OR severe OR ( sourcetype=access_* ( 404 OR 500 OR 503 ) )
        dispatch.earliest_time = -1h
        """
        t2 = """
        [Errors in the last hour
        ]
        search = error OR failed OR severe OR ( sourcetype=access_* ( 404 OR 500 OR 503 ) )
        dispatch.earliest_time = -1h
        """
        t3 = """
        Errors in the last hour]
        search = error OR failed OR severe OR ( sourcetype=access_* ( 404 OR 500 OR 503 ) )
        dispatch.earliest_time = -1h
        """
        # These SHOULD raise an error, even without strict=True
        with self.assertRaises(ConfParserException):
            parse_string(t1)

        with self.assertRaises(ConfParserException):
            parse_string(t2)

        with self.assertRaises(ConfParserException):
            parse_string(t3)
示例#13
0
    def test_preserve_empty_stanza(self):
        c = parse_string("""
        [stanza1]
        key1 = yes
        key2 = no
        [stanza2]

        [stanza3]
        has_key = true
        """)
        self.assertEqual(c["stanza1"]["key1"], "yes")
        self.assertTrue("stanza2" in c, "Must preserve empty stanza")
        self.assertEqual(len(c["stanza2"]), 0)
        self.assertEqual(c["stanza3"]["has_key"], "true")
示例#14
0
    def test_compare_keys_props(self):
        c1 = parse_string(self.cfg_props_imapsync_1)
        c2 = parse_string(self.cfg_props_imapsync_2)
        diffs = compare_cfgs(c1, c2)

        op = self.find_op_by_location(diffs,
                                      "key",
                                      stanza="imapsync",
                                      key="NO_BINARY_CHECK")
        self.assertEqual(op.tag, DIFF_OP_REPLACE)
        self.assertEqual(op.a, "true")
        self.assertEqual(op.b, "false")

        op = self.find_op_by_location(diffs,
                                      "key",
                                      stanza="imapsync",
                                      key="LINE_BREAKER")
        self.assertEqual(op.tag, DIFF_OP_EQUAL)
        self.assertEqual(op.a, op.b)
        self.assertTrue(op.a.startswith(
            r"([\r\n]+)"))  # Don't bother to match the whole thing...

        op = self.find_op_by_location(diffs,
                                      "key",
                                      stanza="imapsync",
                                      key="DATETIME_CONFIG")
        self.assertEqual(op.tag, DIFF_OP_DELETE)
        self.assertIsNone(op.a)
        self.assertIsNotNone(op.b)

        op = self.find_op_by_location(diffs,
                                      "key",
                                      stanza="imapsync",
                                      key="description")
        self.assertEqual(op.tag, DIFF_OP_INSERT)
        self.assertIsNotNone(op.a)
        self.assertIsNone(op.b)
示例#15
0
 def test_multi_stanza(self):
     c = parse_string("""
     [stanza1]
     key1 = yes
     key2 = no
     [stanza2]
     key1 = no
     key2 = yes
     empty =
     """)
     self.assertEqual(c["stanza1"]["key1"], "yes")
     self.assertEqual(c["stanza1"]["key2"], "no")
     self.assertEqual(c["stanza2"]["key1"], "no")
     self.assertEqual(c["stanza2"]["key2"], "yes")
     self.assertEqual(c["stanza2"]["empty"], "")
示例#16
0
 def test_whitespace_keyvalue(self):
     c = parse_string("""
     [stanza1]
     key1=yes
     key2  =   no
     [stanza2]
      key1 =\tred
     key with spaces = not normal
     key2 = green   """)  # Trailing white space on key2
     self.assertEqual(c["stanza1"]["key1"], "yes")
     self.assertEqual(c["stanza1"]["key2"], "no")
     # XXX: This seems wrong...  we probably don't want to preserve whitespace in the key name.
     self.assertEqual(c["stanza2"][" key1"], "red")
     # Todo: Figure out what Splunk behavior is for trailing whitespace.  (For now, should pass)
     self.assertEqual(c["stanza2"]["key2"], "green   ")
     # Todo:  Does this ever happen...
     self.assertTrue(c["stanza2"]["key with spaces"])
示例#17
0
    def test_stanza_weird_chars(self):
        c = parse_string(r"""
        [source::...(/|\\)var(/|\\)log(/|\\)splunk(/|\\)*aws_sns*.log*]
        LINE_BREAKER=([\r\n]+)\d{4}-\d{2}-\d{2}
        sourcetype = aws:sns:alert:log
        priority = 1

        [source::...[/\\]var[/\\]log[/\\]splunk[/\\]s3util*.log*]
        sourcetype = aws:s3util:log
        priority = 10

        [My cool search [COOLNESS]]
        search = ...
        """)
        self.assertTrue(c[r"source::...(/|\\)var(/|\\)log(/|\\)splunk(/|\\)*aws_sns*.log*"])
        self.assertTrue(c[r"source::...[/\\]var[/\\]log[/\\]splunk[/\\]s3util*.log*"])
        self.assertTrue(c["My cool search [COOLNESS]"])
示例#18
0
 def test_whitespace_stanza(self):
     c = parse_string("""
     [stanza 1]
     type = bool
     value = False
     [ stanza2]
     color = yellow
     [stanza 3 ]
     homework = no
      [stanza 4]
     pre_whitespace = weird
     [stanza 5]  """)
     self.assertEqual(c["stanza 1"]["type"], "bool")
     self.assertEqual(c[" stanza2"]["color"], "yellow")
     self.assertEqual(c["stanza 3 "]["homework"], "no")
     # This one fails....   need to confirm Splunk's built-in behavior....  Maybe this should fail on 'strict' mode?
     # self.assertEqual(c["stanza 4"]["pre_whitespace"], "weird")
     self.assertIn("stanza 5", c)
示例#19
0
 def test_continuation(self):
     t = r"""
     [Sourcetype regex reuse]
     description = Determining similarities in sourcetypes based on which share the same EXTRACT regexes
     dispatch.earliest_time = 0
     display.general.type = statistics
     display.page.search.tab = statistics
     display.visualizations.show = 0
     search = | rest /servicesNS/-/-/configs/conf-props \
     | search eai:appName=* NOT title=source::* \
     | table title, EXTRACT-*, TIME_FORMAT, TIME_PREFIX, LINE_BREAKER, SHOULD_LINEMERGE, KV_MODE, sourcetype \
     | rename title as sourcetype \
     | untable sourcetype key value \
     | search key="EXTRACT-*" \
     | eval entry="[".sourcetype . "] " . key \
     | stats count values(entry) as entry by value \
     | where count>1
     """
     c = parse_string(t)
     self.assertEqual(len(c["Sourcetype regex reuse"]["search"].splitlines()), 9)
示例#20
0
 def test_continuation_subsearch(self):
     """ Need to make sure that []"""
     t = r"""
     [Knowledge Object backup to CSV]
     description = Useful tool to export Knowledge Objects when (1) you don't have file-system \
     access, and (2) you only have Splunk Web access (no REST calls).
     search = | makeresults count=1 | \
     eval id="BACKUP-HEADER", now=now(), \
       title="BACKUP DESCRIPTION GOES HERE" \
     | append \
     [ rest splunk_server=local /servicesNS/-/-/data/ui/views ] \
     | append \
     [ rest splunk_server=local /servicesNS/-/-/configs/conf-macros ]
     request.ui_dispatch_view = search
     """
     c = parse_string(t)
     # If an empty global stanza is created, that's an implementation detail not important here.
     self.assertTrue(c["Knowledge Object backup to CSV"])
     self.assertNotIn(" rest splunk_server=local /servicesNS/-/-/configs/conf-macros ", c)
     self.assertEqual(len(c), 1, "Should only have 1 stanza")
     self.assertEqual(len(c["Knowledge Object backup to CSV"]["search"].splitlines()), 7)
示例#21
0
 def test_summarize_compare_results(self):
     c1 = parse_string(self.cfg_props_imapsync_1)
     c2 = parse_string(self.cfg_props_imapsync_2)
     diffs = compare_cfgs(c1, c2)
     output = StringIO()
     summarize_cfg_diffs(diffs, output)