From 83190175338e8158e16a5ea53bb43ad90f9c55fe Mon Sep 17 00:00:00 2001 From: Tom von Schwerdtner Date: Thu, 20 Apr 2017 16:15:44 -0400 Subject: [PATCH 01/14] Pass path as flag --- templates/create_project.py.erb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/templates/create_project.py.erb b/templates/create_project.py.erb index 836ae53..9230219 100755 --- a/templates/create_project.py.erb +++ b/templates/create_project.py.erb @@ -9,7 +9,6 @@ from urllib import quote # Add the project to the python path activate_this = '<%= @path %>/bin/activate_this.py' execfile(activate_this, dict(__file__=activate_this)) -os.environ['SENTRY_CONF'] = '<%= @path %>' from sentry.utils.runner import configure configure() @@ -24,11 +23,15 @@ def build_parser(): parser.add_option("-o", "--org", dest="org", help="Organization to own this project (<%= @organization %>)", type="string", default="<%= @organization %>") parser.add_option("-t", "--team", dest="team", help="Team to own this project (<%= @team %>)", type="string", default="<%= @team %>") parser.add_option("-v", "--verbose", dest="verbose", help="Verbose output", action="store_true") + parser.add_option("-s", "--sentry-path", dest="sentry_path", help="Path to sentry project", action="store_true", required=True) return parser def main(): parser = build_parser() options, _args = parser.parse_args() + + os.environ['SENTRY_CONF'] = options.sentry_path + if not options.project: parser.error("Project name required") if not options.platform: @@ -90,7 +93,8 @@ def main(): # create a static file containing this application's DSN k = ProjectKey.objects.get(project_id=p.id).get_dsn() prefix = quote(o.name.lower() + "-" + t.name.lower() + "-") - dsn = open('<%= @path %>/dsn/' + prefix + p.name, 'a') + dsn_path = "%s/dsn/%s%s" % (options.sentry_path, prefix, p.name) + dsn = open(dsn_path, 'a') dsn.write(k) dsn.close() From 1645b0b60d14d2289c5fcac1827c459fec1aae84 Mon Sep 17 00:00:00 2001 From: Tom von Schwerdtner Date: Thu, 20 Apr 2017 16:17:24 -0400 Subject: [PATCH 02/14] Move to files directory --- templates/create_project.py.erb => files/create_project.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename templates/create_project.py.erb => files/create_project.py (100%) diff --git a/templates/create_project.py.erb b/files/create_project.py similarity index 100% rename from templates/create_project.py.erb rename to files/create_project.py From b49180766bbabac30c9735b99543220076c91a1c Mon Sep 17 00:00:00 2001 From: Tom von Schwerdtner Date: Thu, 20 Apr 2017 16:21:28 -0400 Subject: [PATCH 03/14] Remove env activation --- files/create_project.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/files/create_project.py b/files/create_project.py index 9230219..b912d1d 100755 --- a/files/create_project.py +++ b/files/create_project.py @@ -6,10 +6,6 @@ from optparse import OptionParser from urllib import quote -# Add the project to the python path -activate_this = '<%= @path %>/bin/activate_this.py' -execfile(activate_this, dict(__file__=activate_this)) - from sentry.utils.runner import configure configure() From 3c5dd7dac95a03adadcd5f96882ea34f177dcc57 Mon Sep 17 00:00:00 2001 From: Tom von Schwerdtner Date: Thu, 20 Apr 2017 16:21:43 -0400 Subject: [PATCH 04/14] Remove default templated values and make required --- files/create_project.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/create_project.py b/files/create_project.py index b912d1d..a08d87b 100755 --- a/files/create_project.py +++ b/files/create_project.py @@ -16,8 +16,8 @@ def build_parser(): parser = OptionParser() parser.add_option("-p", "--project", dest="project", help="Application/Project name.", type="string") parser.add_option("-l", "--platform", dest="platform", help="Application Language/Platform.", type="string") - parser.add_option("-o", "--org", dest="org", help="Organization to own this project (<%= @organization %>)", type="string", default="<%= @organization %>") - parser.add_option("-t", "--team", dest="team", help="Team to own this project (<%= @team %>)", type="string", default="<%= @team %>") + parser.add_option("-o", "--org", dest="org", help="Organization to own this project", type="string", required=True) + parser.add_option("-t", "--team", dest="team", help="Team to own this project", type="string", required=True) parser.add_option("-v", "--verbose", dest="verbose", help="Verbose output", action="store_true") parser.add_option("-s", "--sentry-path", dest="sentry_path", help="Path to sentry project", action="store_true", required=True) return parser From 8ad41b4213c4750686273fbe2fd500730f02523f Mon Sep 17 00:00:00 2001 From: Tom von Schwerdtner Date: Thu, 20 Apr 2017 16:23:27 -0400 Subject: [PATCH 05/14] Remove templated values and pass as options --- files/create_project.py | 5 +++-- manifests/source/project.pp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/files/create_project.py b/files/create_project.py index a08d87b..d898fed 100755 --- a/files/create_project.py +++ b/files/create_project.py @@ -20,6 +20,7 @@ def build_parser(): parser.add_option("-t", "--team", dest="team", help="Team to own this project", type="string", required=True) parser.add_option("-v", "--verbose", dest="verbose", help="Verbose output", action="store_true") parser.add_option("-s", "--sentry-path", dest="sentry_path", help="Path to sentry project", action="store_true", required=True) + parser.add_option("-e", "--email", dest="email", help="Email address for administrator", action="store_true", required=True) return parser def main(): @@ -36,9 +37,9 @@ def main(): # try to load the requested organization # and the admin user, who will own all new projects and teams e = False - try: + try: o = Organization.objects.get(name=options.org) - u = User.objects.get(email='<%= @admin_email %>') + u = User.objects.get(email=options.email) except: e = sys.exc_info()[0] if e: diff --git a/manifests/source/project.pp b/manifests/source/project.pp index c2b4916..75a8d6a 100644 --- a/manifests/source/project.pp +++ b/manifests/source/project.pp @@ -49,7 +49,7 @@ # if ! defined( Exec["Add ${organization}-${team}-${project}"] ) { exec { "Add ${organization}-${team}-${project}": - command => "${path}/bin/python ${path}/create_project.py -o ${organization} -t ${team} -l ${platform} -p ${project}", + command => "${path}/bin/python ${path}/create_project.py -o ${organization} -t ${team} -l ${platform} -p ${project} -s ${path} -e ${admin_email}", creates => "${path}/dsn/${p}", require => File["${path}/create_project.py"], } From bf3808d2ab348905bd3a78bedca9450ebe127704 Mon Sep 17 00:00:00 2001 From: Tom von Schwerdtner Date: Thu, 20 Apr 2017 16:27:59 -0400 Subject: [PATCH 06/14] Load as file instead of template --- manifests/init.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifests/init.pp b/manifests/init.pp index 16b39ec..7916855 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -177,7 +177,7 @@ file { "${path}/create_project.py": ensure => present, mode => '0755', - content => template('sentry/create_project.py.erb'), + content => 'puppet:///modules/sentry/create_project.py', require => Class['::sentry::install'], } From 4a214418dfc08250801c06d3064f03270746c812 Mon Sep 17 00:00:00 2001 From: Tom von Schwerdtner Date: Thu, 20 Apr 2017 16:34:19 -0400 Subject: [PATCH 07/14] More idiomatic querying of objects --- files/create_project.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/files/create_project.py b/files/create_project.py index d898fed..8f4d33e 100755 --- a/files/create_project.py +++ b/files/create_project.py @@ -34,16 +34,16 @@ def main(): if not options.platform: parser.error("Platform is required") - # try to load the requested organization - # and the admin user, who will own all new projects and teams - e = False try: o = Organization.objects.get(name=options.org) + except Organization.DoesNotExist: + print "Organization not found: %s" % options.org + sys.exit(1) + + try: u = User.objects.get(email=options.email) - except: - e = sys.exc_info()[0] - if e: - print "Error loading Sentry environment: %s" % (e) + except User.DoesNotExist: + print "Admin user not found: %s" % options.email sys.exit(1) # try to load the requested team From 618923ea0bae71352cdc765d31c7484be02de22d Mon Sep 17 00:00:00 2001 From: Tom von Schwerdtner Date: Thu, 20 Apr 2017 16:40:04 -0400 Subject: [PATCH 08/14] Parse admin email from sentry config --- files/create_project.py | 14 +++++++++++--- manifests/source/project.pp | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/files/create_project.py b/files/create_project.py index 8f4d33e..a62ba15 100755 --- a/files/create_project.py +++ b/files/create_project.py @@ -5,6 +5,7 @@ import os, sys, site from optparse import OptionParser from urllib import quote +import yaml from sentry.utils.runner import configure configure() @@ -20,15 +21,22 @@ def build_parser(): parser.add_option("-t", "--team", dest="team", help="Team to own this project", type="string", required=True) parser.add_option("-v", "--verbose", dest="verbose", help="Verbose output", action="store_true") parser.add_option("-s", "--sentry-path", dest="sentry_path", help="Path to sentry project", action="store_true", required=True) - parser.add_option("-e", "--email", dest="email", help="Email address for administrator", action="store_true", required=True) return parser +def read_sentry_config(path): + with open("%s/config.yml" % path, 'r') as sentry_config: + data = yaml.load(sentry_config) + + return data['system.admin-email'] + def main(): parser = build_parser() options, _args = parser.parse_args() os.environ['SENTRY_CONF'] = options.sentry_path + admin_email = read_sentry_config(options.sentry_path) + if not options.project: parser.error("Project name required") if not options.platform: @@ -41,9 +49,9 @@ def main(): sys.exit(1) try: - u = User.objects.get(email=options.email) + u = User.objects.get(email=admin_email) except User.DoesNotExist: - print "Admin user not found: %s" % options.email + print "Admin user not found: %s" % admin_email sys.exit(1) # try to load the requested team diff --git a/manifests/source/project.pp b/manifests/source/project.pp index 75a8d6a..a93a41e 100644 --- a/manifests/source/project.pp +++ b/manifests/source/project.pp @@ -49,7 +49,7 @@ # if ! defined( Exec["Add ${organization}-${team}-${project}"] ) { exec { "Add ${organization}-${team}-${project}": - command => "${path}/bin/python ${path}/create_project.py -o ${organization} -t ${team} -l ${platform} -p ${project} -s ${path} -e ${admin_email}", + command => "${path}/bin/python ${path}/create_project.py -o ${organization} -t ${team} -l ${platform} -p ${project} -s ${path}", creates => "${path}/dsn/${p}", require => File["${path}/create_project.py"], } From 9020420bddb1b78ba45a4c1ca57fd99f939efafe Mon Sep 17 00:00:00 2001 From: Tom von Schwerdtner Date: Thu, 20 Apr 2017 16:52:46 -0400 Subject: [PATCH 09/14] Read admin email from sentry settings --- files/create_project.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/files/create_project.py b/files/create_project.py index a62ba15..478dbde 100755 --- a/files/create_project.py +++ b/files/create_project.py @@ -5,7 +5,6 @@ import os, sys, site from optparse import OptionParser from urllib import quote -import yaml from sentry.utils.runner import configure configure() @@ -13,6 +12,8 @@ # Add in the sentry object models from sentry.models import Organization, Project, ProjectKey, Team, User +from django.conf import settings + def build_parser(): parser = OptionParser() parser.add_option("-p", "--project", dest="project", help="Application/Project name.", type="string") @@ -23,19 +24,13 @@ def build_parser(): parser.add_option("-s", "--sentry-path", dest="sentry_path", help="Path to sentry project", action="store_true", required=True) return parser -def read_sentry_config(path): - with open("%s/config.yml" % path, 'r') as sentry_config: - data = yaml.load(sentry_config) - - return data['system.admin-email'] - def main(): parser = build_parser() options, _args = parser.parse_args() os.environ['SENTRY_CONF'] = options.sentry_path - admin_email = read_sentry_config(options.sentry_path) + admin_email = settings.SENTRY_OPTIONS['system.admin-email'] if not options.project: parser.error("Project name required") From ff027a1703a63285df89c99b011c68e732538a61 Mon Sep 17 00:00:00 2001 From: Tom von Schwerdtner Date: Thu, 20 Apr 2017 16:56:39 -0400 Subject: [PATCH 10/14] Do not fail if project exists --- files/create_project.py | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/files/create_project.py b/files/create_project.py index 478dbde..c8aff70 100755 --- a/files/create_project.py +++ b/files/create_project.py @@ -65,36 +65,25 @@ def main(): try: p = Project.objects.get(name=options.project,team_id=t.id) except: - p = False - - if p: - if options.verbose: - print 'Project %s exists in team %s' % (options.project, t.name) - sys.exit(1) - - # the project doesn't exist. Create it! - p = Project() - # ensure all project names are in lowercase - p.name = options.project.lower() - p.team_id = t.id - p.organization_id = o.id - p.platform = options.platform - try: - p.save() - except: - e = sys.exc_info()[0] - - if e: - # an error occured - if options.verbose: + # the project doesn't exist. Create it! + p = Project() + # ensure all project names are in lowercase + p.name = options.project.lower() + p.team_id = t.id + p.organization_id = o.id + p.platform = options.platform + + try: + p.save() + except: print "Project save failed for %s: %s" % (options.project, e) - sys.exit(1) + sys.exit(1) # create a static file containing this application's DSN k = ProjectKey.objects.get(project_id=p.id).get_dsn() prefix = quote(o.name.lower() + "-" + t.name.lower() + "-") dsn_path = "%s/dsn/%s%s" % (options.sentry_path, prefix, p.name) - dsn = open(dsn_path, 'a') + dsn = open(dsn_path, 'w') dsn.write(k) dsn.close() From 89b3d19cdc4493c441b476cd1fd3cb8b9ad858c7 Mon Sep 17 00:00:00 2001 From: Adam Stephens Date: Thu, 20 Apr 2017 17:35:13 -0400 Subject: [PATCH 11/14] fix file source since no longer a template --- manifests/init.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifests/init.pp b/manifests/init.pp index 7916855..0b2b47e 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -177,7 +177,7 @@ file { "${path}/create_project.py": ensure => present, mode => '0755', - content => 'puppet:///modules/sentry/create_project.py', + source => 'puppet:///modules/sentry/create_project.py', require => Class['::sentry::install'], } From 61eb312955baf905d56fe882d3f8e21e3e45bd5f Mon Sep 17 00:00:00 2001 From: Adam Stephens Date: Thu, 20 Apr 2017 17:45:45 -0400 Subject: [PATCH 12/14] required is not an optparse option, and updates for pep-8 --- files/create_project.py | 141 ++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 69 deletions(-) diff --git a/files/create_project.py b/files/create_project.py index c8aff70..716c7de 100755 --- a/files/create_project.py +++ b/files/create_project.py @@ -2,93 +2,96 @@ # This script checks to see if a project exists for the given # app_env/team. # -import os, sys, site +import os +import sys from optparse import OptionParser from urllib import quote -from sentry.utils.runner import configure -configure() - # Add in the sentry object models from sentry.models import Organization, Project, ProjectKey, Team, User - from django.conf import settings +from sentry.utils.runner import configure +configure() + + def build_parser(): parser = OptionParser() parser.add_option("-p", "--project", dest="project", help="Application/Project name.", type="string") parser.add_option("-l", "--platform", dest="platform", help="Application Language/Platform.", type="string") - parser.add_option("-o", "--org", dest="org", help="Organization to own this project", type="string", required=True) - parser.add_option("-t", "--team", dest="team", help="Team to own this project", type="string", required=True) + parser.add_option("-o", "--org", dest="org", help="Organization to own this project", type="string") + parser.add_option("-t", "--team", dest="team", help="Team to own this project", type="string") parser.add_option("-v", "--verbose", dest="verbose", help="Verbose output", action="store_true") - parser.add_option("-s", "--sentry-path", dest="sentry_path", help="Path to sentry project", action="store_true", required=True) + parser.add_option("-s", "--sentry-path", dest="sentry_path", help="Path to sentry project", action="store_true") return parser + def main(): - parser = build_parser() - options, _args = parser.parse_args() - - os.environ['SENTRY_CONF'] = options.sentry_path - - admin_email = settings.SENTRY_OPTIONS['system.admin-email'] - - if not options.project: - parser.error("Project name required") - if not options.platform: - parser.error("Platform is required") - - try: - o = Organization.objects.get(name=options.org) - except Organization.DoesNotExist: - print "Organization not found: %s" % options.org - sys.exit(1) - - try: - u = User.objects.get(email=admin_email) - except User.DoesNotExist: - print "Admin user not found: %s" % admin_email - sys.exit(1) - - # try to load the requested team - try: - t = Team.objects.get(name=options.team,organization_id=o.id) - except Team.DoesNotExist: - # this team does not yet exist. Create it. - t = Team() - t.name = options.team - t.organization_id = o.id - t.owner_id = u.id - t.save() - # reload the object - t = Team.objects.get(name=options.team,organization_id=o.id) - - try: - p = Project.objects.get(name=options.project,team_id=t.id) - except: - # the project doesn't exist. Create it! - p = Project() - # ensure all project names are in lowercase - p.name = options.project.lower() - p.team_id = t.id - p.organization_id = o.id - p.platform = options.platform + parser = build_parser() + options, _args = parser.parse_args() + + os.environ['SENTRY_CONF'] = options.sentry_path + + admin_email = settings.SENTRY_OPTIONS['system.admin-email'] + + if not options.project: + parser.error("Project name required") + if not options.platform: + parser.error("Platform is required") try: - p.save() - except: - print "Project save failed for %s: %s" % (options.project, e) - sys.exit(1) + o = Organization.objects.get(name=options.org) + except Organization.DoesNotExist: + print "Organization not found: %s" % options.org + sys.exit(1) + + try: + u = User.objects.get(email=admin_email) + except User.DoesNotExist: + print "Admin user not found: %s" % admin_email + sys.exit(1) - # create a static file containing this application's DSN - k = ProjectKey.objects.get(project_id=p.id).get_dsn() - prefix = quote(o.name.lower() + "-" + t.name.lower() + "-") - dsn_path = "%s/dsn/%s%s" % (options.sentry_path, prefix, p.name) - dsn = open(dsn_path, 'w') - dsn.write(k) - dsn.close() + # try to load the requested team + try: + t = Team.objects.get(name=options.team, organization_id=o.id) + except Team.DoesNotExist: + # this team does not yet exist. Create it. + t = Team() + t.name = options.team + t.organization_id = o.id + t.owner_id = u.id + t.save() + # reload the object + t = Team.objects.get(name=options.team, organization_id=o.id) + + try: + p = Project.objects.get(name=options.project, team_id=t.id) + except: + # the project doesn't exist. Create it! + p = Project() + # ensure all project names are in lowercase + p.name = options.project.lower() + p.team_id = t.id + p.organization_id = o.id + p.platform = options.platform + + try: + p.save() + except: + print "Project save failed for %s" % (options.project) + sys.exit(1) + + # create a static file containing this application's DSN + k = ProjectKey.objects.get(project_id=p.id).get_dsn() + prefix = quote(o.name.lower() + "-" + t.name.lower() + "-") + dsn_path = "%s/dsn/%s%s" % (options.sentry_path, prefix, p.name) + dsn = open(dsn_path, 'w') + dsn.write(k) + dsn.close() + + if options.verbose: + print "Project %s created in team %s." % (options.project, t.name) - if options.verbose: - print "Project %s created in team %s." % (options.project, t.name) if __name__ == "__main__": - main() + main() From fe7419074382a79714d28095816751e570dd2202 Mon Sep 17 00:00:00 2001 From: Tom von Schwerdtner Date: Fri, 21 Apr 2017 10:14:20 -0400 Subject: [PATCH 13/14] Import models after configuration --- files/create_project.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/files/create_project.py b/files/create_project.py index 716c7de..cad5238 100755 --- a/files/create_project.py +++ b/files/create_project.py @@ -7,13 +7,14 @@ from optparse import OptionParser from urllib import quote -# Add in the sentry object models -from sentry.models import Organization, Project, ProjectKey, Team, User -from django.conf import settings - from sentry.utils.runner import configure configure() +from django.conf import settings + +# Add in the sentry object models +from sentry.models import Organization, Project, ProjectKey, Team, User + def build_parser(): parser = OptionParser() From 1a6516765f7d95d8a3d89449dc181a9de27cb868 Mon Sep 17 00:00:00 2001 From: Tom von Schwerdtner Date: Fri, 21 Apr 2017 10:44:01 -0400 Subject: [PATCH 14/14] Shove the input into the main method --- files/create_project.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/files/create_project.py b/files/create_project.py index cad5238..9add9c8 100755 --- a/files/create_project.py +++ b/files/create_project.py @@ -7,14 +7,6 @@ from optparse import OptionParser from urllib import quote -from sentry.utils.runner import configure -configure() - -from django.conf import settings - -# Add in the sentry object models -from sentry.models import Organization, Project, ProjectKey, Team, User - def build_parser(): parser = OptionParser() @@ -23,7 +15,7 @@ def build_parser(): parser.add_option("-o", "--org", dest="org", help="Organization to own this project", type="string") parser.add_option("-t", "--team", dest="team", help="Team to own this project", type="string") parser.add_option("-v", "--verbose", dest="verbose", help="Verbose output", action="store_true") - parser.add_option("-s", "--sentry-path", dest="sentry_path", help="Path to sentry project", action="store_true") + parser.add_option("-s", "--sentry-path", dest="sentry_path", help="Path to sentry project", type="string") return parser @@ -33,6 +25,13 @@ def main(): os.environ['SENTRY_CONF'] = options.sentry_path + from sentry.utils.runner import configure + configure() + + from django.conf import settings + # Add in the sentry object models + from sentry.models import Organization, Project, ProjectKey, Team, User + admin_email = settings.SENTRY_OPTIONS['system.admin-email'] if not options.project: