Browse Source

migration(plugins): use aws sqs plugin from sentry core (#15428)

Stephen Cefali 5 years ago
parent
commit
22f4105092

+ 1 - 1
conftest.py

@@ -32,7 +32,7 @@ def install_sentry_plugins():
     from sentry.runner.importer import install_plugin_apps
     from django.conf import settings
 
-    install_plugin_apps("sentry.new_apps", settings)
+    install_plugin_apps("sentry.test_only_apps", settings)
 
     from sentry.runner.initializer import register_plugins
 

+ 24 - 22
setup.py

@@ -140,31 +140,33 @@ setup(
     include_package_data=True,
     entry_points={
         "console_scripts": ["sentry = sentry.runner:main"],
-        "sentry.new_apps": [
-            "jira_ac = new_sentry_plugins.jira_ac",
-            "jira = new_sentry_plugins.jira",
-            "sessionstack = new_sentry_plugins.sessionstack",
+        "sentry.test_only_apps": [
+            "jira_ac = test_only_plugins.jira_ac",
+            "jira = test_only_plugins.jira",
+            "sessionstack = test_only_plugins.sessionstack",
         ],
         "sentry.new_plugins": [
             "amazon_sqs = new_sentry_plugins.amazon_sqs.plugin:AmazonSQSPlugin",
-            "asana = new_sentry_plugins.asana.plugin:AsanaPlugin",
-            "bitbucket = new_sentry_plugins.bitbucket.plugin:BitbucketPlugin",
-            "clubhouse = new_sentry_plugins.clubhouse.plugin:ClubhousePlugin",
-            "github = new_sentry_plugins.github.plugin:GitHubPlugin",
-            "gitlab = new_sentry_plugins.gitlab.plugin:GitLabPlugin",
-            "heroku = new_sentry_plugins.heroku.plugin:HerokuPlugin",
-            "jira = new_sentry_plugins.jira.plugin:JiraPlugin",
-            "jira_ac = new_sentry_plugins.jira_ac.plugin:JiraACPlugin",
-            "pagerduty = new_sentry_plugins.pagerduty.plugin:PagerDutyPlugin",
-            "phabricator = new_sentry_plugins.phabricator.plugin:PhabricatorPlugin",
-            "pivotal = new_sentry_plugins.pivotal.plugin:PivotalPlugin",
-            "pushover = new_sentry_plugins.pushover.plugin:PushoverPlugin",
-            "segment = new_sentry_plugins.segment.plugin:SegmentPlugin",
-            "sessionstack = new_sentry_plugins.sessionstack.plugin:SessionStackPlugin",
-            "slack = new_sentry_plugins.slack.plugin:SlackPlugin",
-            "splunk = new_sentry_plugins.splunk.plugin:SplunkPlugin",
-            "victorops = new_sentry_plugins.victorops.plugin:VictorOpsPlugin",
-            "vsts = new_sentry_plugins.vsts.plugin:VstsPlugin",
+        ],
+        "sentry.test_only_plugins": [
+            "asana = test_only_plugins.asana.plugin:AsanaPlugin",
+            "bitbucket = test_only_plugins.bitbucket.plugin:BitbucketPlugin",
+            "clubhouse = test_only_plugins.clubhouse.plugin:ClubhousePlugin",
+            "github = test_only_plugins.github.plugin:GitHubPlugin",
+            "gitlab = test_only_plugins.gitlab.plugin:GitLabPlugin",
+            "heroku = test_only_plugins.heroku.plugin:HerokuPlugin",
+            "jira = test_only_plugins.jira.plugin:JiraPlugin",
+            "jira_ac = test_only_plugins.jira_ac.plugin:JiraACPlugin",
+            "pagerduty = test_only_plugins.pagerduty.plugin:PagerDutyPlugin",
+            "phabricator = test_only_plugins.phabricator.plugin:PhabricatorPlugin",
+            "pivotal = test_only_plugins.pivotal.plugin:PivotalPlugin",
+            "pushover = test_only_plugins.pushover.plugin:PushoverPlugin",
+            "segment = test_only_plugins.segment.plugin:SegmentPlugin",
+            "sessionstack = test_only_plugins.sessionstack.plugin:SessionStackPlugin",
+            "slack = test_only_plugins.slack.plugin:SlackPlugin",
+            "splunk = test_only_plugins.splunk.plugin:SplunkPlugin",
+            "victorops = test_only_plugins.victorops.plugin:VictorOpsPlugin",
+            "vsts = test_only_plugins.vsts.plugin:VstsPlugin",
         ],
     },
     classifiers=[

+ 1 - 0
src/new_sentry_plugins/__init__.py

@@ -1,3 +1,4 @@
+
 from __future__ import absolute_import
 
 try:

+ 4 - 4
src/new_sentry_plugins/base.py

@@ -1,18 +1,18 @@
 from __future__ import absolute_import
 
 import pkg_resources
-import new_sentry_plugins
+import test_only_plugins
 import six
 import sys
 
 from sentry.exceptions import InvalidIdentity, PluginError
 
-from new_sentry_plugins.constants import (
+from test_only_plugins.constants import (
     ERR_INTERNAL,
     ERR_UNAUTHORIZED,
     ERR_UNSUPPORTED_RESPONSE_TYPE,
 )
-from new_sentry_plugins.exceptions import (
+from test_only_plugins.exceptions import (
     ApiError,
     ApiHostError,
     ApiUnauthorized,
@@ -23,7 +23,7 @@ from new_sentry_plugins.exceptions import (
 class CorePluginMixin(object):
     author = "Sentry Team"
     author_url = "https://github.com/getsentry/sentry-plugins"
-    version = new_sentry_plugins.VERSION
+    version = test_only_plugins.VERSION
     resource_links = [
         ("Bug Tracker", "https://github.com/getsentry/sentry-plugins/issues"),
         ("Source", "https://github.com/getsentry/sentry-plugins"),

+ 0 - 7
src/new_sentry_plugins/github/__init__.py

@@ -1,7 +0,0 @@
-from __future__ import absolute_import
-
-from new_sentry_plugins.base import assert_package_not_installed
-
-assert_package_not_installed("sentry-github")
-
-from new_sentry_plugins.github import options  # NOQA

+ 16 - 12
src/sentry/runner/initializer.py

@@ -20,19 +20,23 @@ def register_plugins(settings, test_plugins=False):
     #         'phabricator = sentry_phabricator.plugins:PhabricatorPlugin'
     #     ],
     # },
-    # TODO (Steve): Remove option for test_plugins
-    entry_point = "sentry.new_plugins" if test_plugins else "sentry.plugins"
-    for ep in iter_entry_points(entry_point):
-        try:
-            plugin = ep.load()
-        except Exception:
-            import traceback
+    entry_points = [
+        "sentry.new_plugins",
+        "sentry.test_only_plugins" if test_plugins else "sentry.plugins",
+    ]
 
-            click.echo(
-                "Failed to load plugin %r:\n%s" % (ep.name, traceback.format_exc()), err=True
-            )
-        else:
-            plugins.register(plugin)
+    for entry_point in entry_points:
+        for ep in iter_entry_points(entry_point):
+            try:
+                plugin = ep.load()
+            except Exception:
+                import traceback
+
+                click.echo(
+                    "Failed to load plugin %r:\n%s" % (ep.name, traceback.format_exc()), err=True
+                )
+            else:
+                plugins.register(plugin)
 
     for plugin in plugins.all(version=None):
         init_plugin(plugin)

+ 16 - 2
src/sentry/testutils/cases.py

@@ -675,8 +675,8 @@ class PluginTestCase(TestCase):
         self.fail("Missing app from entry_points: %r" % (name,))
 
     # TODO (Steve): remove function
-    def assertNewAppInstalled(self, name, path):
-        for ep in iter_entry_points("sentry.new_apps"):
+    def assertTestOnlyAppInstalled(self, name, path):
+        for ep in iter_entry_points("sentry.test_only_apps"):
             if ep.name == name:
                 ep_path = ep.module_name
                 if ep_path == path:
@@ -700,6 +700,20 @@ class PluginTestCase(TestCase):
                 )
         self.fail("Missing plugin from entry_points: %r" % (name,))
 
+    # TODO (Steve): remove function
+    def assertTestOnlyPluginInstalled(self, name, plugin):
+        path = type(plugin).__module__ + ":" + type(plugin).__name__
+        for ep in iter_entry_points("sentry.test_only_plugins"):
+            if ep.name == name:
+                ep_path = ep.module_name + ":" + ".".join(ep.attrs)
+                if ep_path == path:
+                    return
+                self.fail(
+                    "Found plugin in entry_points, but wrong class. Got %r, expected %r"
+                    % (ep_path, path)
+                )
+        self.fail("Missing plugin from entry_points: %r" % (name,))
+
     # TODO (Steve): remove function
     def assertNewPluginInstalled(self, name, plugin):
         path = type(plugin).__module__ + ":" + type(plugin).__name__

+ 6 - 0
src/test_only_plugins/__init__.py

@@ -0,0 +1,6 @@
+from __future__ import absolute_import
+
+try:
+    VERSION = __import__("pkg_resources").get_distribution("sentry-plugins").version
+except Exception:
+    VERSION = "unknown"

+ 126 - 0
src/test_only_plugins/anonymizeip.py

@@ -0,0 +1,126 @@
+# Port of https://github.com/samuelmeuli/anonymize-ip to Python 2
+"""
+MIT License
+
+Copyright (c) 2018 Samuel Meuli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+from __future__ import absolute_import, unicode_literals
+
+import six
+
+from ipaddress import ip_address
+
+
+def anonymize_ip(
+    address, ipv4_mask="255.255.255.0", ipv6_mask="ffff:ffff:ffff:0000:0000:0000:0000:0000"
+):
+    """
+    Anonymize the provided IPv4 or IPv6 address by setting parts of the
+    address to 0
+    :param str|int address: IP address to be anonymized
+    :param str ipv4_mask: Mask that defines which parts of an IPv4 address are
+    set to 0 (default: "255.255.255.0")
+    :param str ipv6_mask: Mask that defines which parts of an IPv6 address are
+    set to 0 (default: "ffff:ffff:ffff:0000:0000:0000:0000:0000")
+    :return: Anonymized IP address
+    :rtype: str
+    """
+
+    # IP address to be anonymized
+    address_packed = ip_address(six.text_type(address)).packed
+    address_len = len(address_packed)
+
+    if address_len == 4:
+        # IPv4
+        ipv4_mask_packed = ip_address(ipv4_mask).packed
+        __validate_ipv4_mask(ipv4_mask_packed)
+        return __apply_mask(address_packed, ipv4_mask_packed, 4)
+    elif address_len == 16:
+        # IPv6
+        ipv6_mask_packed = ip_address(ipv6_mask).packed
+        __validate_ipv6_mask(ipv6_mask_packed)
+        return __apply_mask(address_packed, ipv6_mask_packed, 16)
+    else:
+        # Invalid address
+        raise ValueError("Address does not consist of 4 (IPv4) or 16 (IPv6) " "octets")
+
+
+def __apply_mask(address_packed, mask_packed, nr_bytes):
+    """
+    Perform a bitwise AND operation on all corresponding bytes between the
+    mask and the provided address. Mask parts set to 0 will become 0 in the
+    anonymized IP address as well
+    :param bytes address_packed: Binary representation of the IP address to
+    be anonymized
+    :param bytes mask_packed: Binary representation of the corresponding IP
+    address mask
+    :param int nr_bytes: Number of bytes in the address (4 for IPv4, 16 for
+    IPv6)
+    :return: Anonymized IP address
+    :rtype: str
+    """
+
+    anon_packed = bytearray()
+    for i in range(0, nr_bytes):
+        anon_packed.append(ord(mask_packed[i]) & ord(address_packed[i]))
+    return six.text_type(ip_address(six.binary_type(anon_packed)))
+
+
+def __validate_ipv4_mask(mask_packed):
+    # Test that mask only contains valid numbers
+    for byte in mask_packed:
+        if byte != b"\x00" and byte != b"\xff":
+            raise ValueError("ipv4_mask must only contain numbers 0 or 255")
+
+    # Test that IP address does not get anonymized completely
+    if mask_packed == b"\x00\x00\x00\x00":
+        raise ValueError(
+            'ipv4_mask cannot be set to "0.0.0.0" (all ' "anonymized addresses will be 0.0.0.0)"
+        )
+
+    # Test that IP address is changed by anonymization
+    if mask_packed == b"\xff\xff\xff\xff":
+        raise ValueError(
+            'ipv4_mask cannot be set to "255.255.255.255" ' "(addresses will not be anonymized)"
+        )
+
+
+def __validate_ipv6_mask(mask_packed):
+    # Test that mask only contains valid numbers
+    for byte in mask_packed:
+        if byte != b"\x00" and byte != b"\xff":
+            raise ValueError("ipv6_mask must only contain numbers 0 or ffff")
+
+    # Test that IP address does not get anonymized completely
+    if mask_packed == b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00":
+        raise ValueError(
+            "ipv6_mask cannot be set to "
+            '"0000:0000:0000:0000:0000:0000:0000:0000" (all '
+            "anonymized addresses will be 0.0.0.0)"
+        )
+
+    # Test that IP address is changed by anonymization
+    if mask_packed == b"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff":
+        raise ValueError(
+            "ipv6_mask cannot be set to "
+            '"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" '
+            "(addresses will not be anonymized)"
+        )

+ 0 - 0
src/new_sentry_plugins/asana/README.rst → src/test_only_plugins/asana/README.rst


Some files were not shown because too many files changed in this diff