def transfer_to(self, team): from sentry.models import ReleaseProject organization = team.organization # We only need to delete ReleaseProjects when moving to a different # Organization. Releases are bound to Organization, so it's not realistic # to keep this link unless we say, copied all Releases as well. if self.organization_id != organization.id: ReleaseProject.objects.filter( project_id=self.id, ).delete() self.organization = organization self.team = team try: with transaction.atomic(): self.update( organization=organization, team=team, ) except IntegrityError: slugify_instance(self, self.name, organization=organization) self.update( slug=self.slug, organization=organization, team=team, )
def save(self, *args, **kwargs): if not self.slug: lock = locks.get('slug:organization', duration=5) with TimedRetryPolicy(10)(lock.acquire): slugify_instance(self, self.name, reserved=RESERVED_ORGANIZATION_SLUGS) super(Organization, self).save(*args, **kwargs) else: super(Organization, self).save(*args, **kwargs)
def save(self, *args, **kwargs): if not self.slug: lock_key = 'slug:team' with Lock(lock_key): slugify_instance(self, self.name, organization=self.organization) super(Team, self).save(*args, **kwargs) else: super(Team, self).save(*args, **kwargs)
def save(self, *args, **kwargs): if not self.slug: lock_key = "slug:project" with Lock(lock_key): slugify_instance(self, self.name, organization=self.organization) super(Project, self).save(*args, **kwargs) else: super(Project, self).save(*args, **kwargs)
def save(self, *args, **kwargs): if not self.slug: lock_key = "slug:organization" with Lock(lock_key): slugify_instance(self, self.name, reserved=RESERVED_ORGANIZATION_SLUGS) super(Organization, self).save(*args, **kwargs) else: super(Organization, self).save(*args, **kwargs)
def save(self, *args, **kwargs): if not self.slug: lock = locks.get('slug:project', duration=5) with TimedRetryPolicy(10)(lock.acquire): slugify_instance(self, self.name, organization=self.organization) super(Project, self).save(*args, **kwargs) else: super(Project, self).save(*args, **kwargs)
def save(self, *args, **kwargs): if not self.slug: lock_key = 'slug:organization' with Lock(lock_key): slugify_instance(self, self.name, reserved=RESERVED_ORGANIZATION_SLUGS) super(Organization, self).save(*args, **kwargs) else: super(Organization, self).save(*args, **kwargs)
def save(self, *args, **kwargs): if not self.slug: lock_key = 'slug:project' with Lock(lock_key): slugify_instance(self, self.name, organization=self.organization) super(Project, self).save(*args, **kwargs) else: super(Project, self).save(*args, **kwargs)
def save(self, *args, **kwargs): if not self.slug: lock = locks.get("slug:team", duration=5) with TimedRetryPolicy(10)(lock.acquire): slugify_instance(self, self.name, organization=self.organization) super().save(*args, **kwargs) else: super().save(*args, **kwargs)
def merge_to(from_org, to_org): from sentry.models import ( ApiKey, AuditLogEntry, OrganizationMember, OrganizationMemberTeam, Project, Team ) for from_member in OrganizationMember.objects.filter(organization=from_org): try: to_member = OrganizationMember.objects.get( organization=to_org, user=from_member.user, ) except OrganizationMember.DoesNotExist: from_member.update(organization=to_org) to_member = from_member else: qs = OrganizationMemberTeam.objects.filter( organizationmember=from_member, is_active=True, ).select_related() for omt in qs: OrganizationMemberTeam.objects.create_or_update( organizationmember=to_member, team=omt.team, defaults={ 'is_active': True, }, ) for team in Team.objects.filter(organization=from_org): try: with transaction.atomic(): team.update(organization=to_org) except IntegrityError: slugify_instance(team, team.name, organization=to_org) team.update( organization=to_org, slug=team.slug, ) for project in Project.objects.filter(organization=from_org): try: with transaction.atomic(): project.update(organization=to_org) except IntegrityError: slugify_instance(project, project.name, organization=to_org) project.update( organization=to_org, slug=project.slug, ) for model in (ApiKey, AuditLogEntry): model.objects.filter( organization=from_org, ).update(organization=to_org)
def save(self, *args, **kwargs): if not self.slug: lock = locks.get("slug:project", duration=5) with TimedRetryPolicy(10)(lock.acquire): slugify_instance( self, self.name, organization=self.organization, reserved=RESERVED_PROJECT_SLUGS ) super(Project, self).save(*args, **kwargs) else: super(Project, self).save(*args, **kwargs) self.update_rev_for_option()
def save(self, *args, **kwargs): if not self.slug: lock = locks.get('slug:project', duration=5) with TimedRetryPolicy(10)(lock.acquire): slugify_instance( self, self.name, organization=self.organization, reserved=RESERVED_PROJECT_SLUGS) super(Project, self).save(*args, **kwargs) else: super(Project, self).save(*args, **kwargs) self.update_rev_for_option()
def forwards(self, orm): from sentry.constants import RESERVED_ORGANIZATION_SLUGS from sentry.db.models.utils import slugify_instance from sentry.utils.query import RangeQuerySetWrapperWithProgressBar Organization = orm['sentry.Organization'] queryset = Organization.objects.filter(slug__isnull=True) for org in RangeQuerySetWrapperWithProgressBar(queryset): slugify_instance(org, org.name, RESERVED_ORGANIZATION_SLUGS) org.save() transaction.commit()
def create_team_and_keys_for_project(instance, created, **kwargs): if not created or kwargs.get('raw'): return if not ProjectKey.objects.filter(project=instance, user__isnull=True).exists(): ProjectKey.objects.create(project=instance, ) if not instance.owner: return if not instance.team: team = Team(owner=instance.owner, name=instance.name) slugify_instance(team, instance.slug) team.save() update(instance, team=team)
def create_team_and_keys_for_project(instance, created, **kwargs): if not created or kwargs.get('raw'): return if not instance.owner: return if not instance.team: team = Team(owner=instance.owner, name=instance.name) slugify_instance(team, instance.slug) team.save() update(instance, team=team) if not ProjectKey.objects.filter(project=instance, user__isnull=True).exists(): ProjectKey.objects.create( project=instance, )
def transfer_to(self, team): # TODO(jess): refactor this to make it an org transfer only from sentry.models import ProjectTeam, ReleaseProject organization = team.organization from_team_id = self.team_id old_org_id = self.organization_id org_changed = old_org_id != organization.id # We only need to delete ReleaseProjects when moving to a different # Organization. Releases are bound to Organization, so it's not realistic # to keep this link unless we say, copied all Releases as well. if org_changed: ReleaseProject.objects.filter(project_id=self.id, ).delete() self.organization = organization self.team = team try: with transaction.atomic(): self.update( organization=organization, team=team, ) except IntegrityError: slugify_instance(self, self.name, organization=organization) self.update( slug=self.slug, organization=organization, team=team, ) ProjectTeam.objects.filter(project=self, team_id=from_team_id).update(team=team) # this is getting really gross, but make sure there aren't lingering associations # with old orgs or teams if org_changed: ProjectTeam.objects.filter( project=self, team__organization_id=old_org_id).delete() # ensure this actually exists in case from team was null self.add_team(team)
def forwards(self, orm): from sentry.constants import RESERVED_ORGANIZATION_SLUGS from sentry.db.models.utils import slugify_instance from sentry.utils.query import RangeQuerySetWrapperWithProgressBar Project = orm['sentry.Project'] queryset = Project.objects.filter( organization__isnull=True ).select_related('team', 'team__organization') for project in RangeQuerySetWrapperWithProgressBar(queryset): project.organization = project.team.organization try: atomic_save(project) except IntegrityError: # we also need to update the slug here based on the new constraints slugify_instance(project, project.name, ( models.Q(organization=project.organization) | models.Q(team=project.team), )) project.save()
def forwards(self, orm): from sentry.constants import RESERVED_ORGANIZATION_SLUGS from sentry.db.models.utils import slugify_instance from sentry.utils.query import RangeQuerySetWrapperWithProgressBar Project = orm['sentry.Project'] queryset = Project.objects.filter( organization__isnull=True).select_related('team', 'team__organization') for project in RangeQuerySetWrapperWithProgressBar(queryset): project.organization = project.team.organization try: atomic_save(project) except IntegrityError: # we also need to update the slug here based on the new constraints slugify_instance(project, project.name, (models.Q(organization=project.organization) | models.Q(team=project.team), )) project.save()
def handle(self, **options): from django.db.models import Q from sentry.constants import RESERVED_ORGANIZATION_SLUGS from sentry.models import Organization, Project, Team, ProjectKey from sentry.db.models import update from sentry.db.models.utils import slugify_instance from sentry.utils.query import RangeQuerySetWrapperWithProgressBar print("Correcting data on organizations") queryset = Organization.objects.filter( slug__isnull=True, ) for org in RangeQuerySetWrapperWithProgressBar(queryset): slugify_instance(org, org.name, RESERVED_ORGANIZATION_SLUGS) org.save() # Create teams for any projects that are missing them print("Correcting data on projects") queryset = Project.objects.filter( Q(team__isnull=True) | Q(organization__isnull=True), ).select_related('owner') for project in RangeQuerySetWrapperWithProgressBar(queryset): if not project.team: organization = Organization( name=project.name, owner=project.owner, ) slugify_instance(organization, organization.name, RESERVED_ORGANIZATION_SLUGS) organization.save() team = Team( name=project.name, owner=project.owner, oprganization=organization, ) slugify_instance(team, team.name, RESERVED_ORGANIZATION_SLUGS) team.save() update(project, organization=team.organization, team=team) # Create missing project keys print("Creating missing project keys") queryset = Team.objects.all() for team in RangeQuerySetWrapperWithProgressBar(queryset): for member in team.member_set.select_related('user'): for project in team.project_set.all(): try: created = ProjectKey.objects.get_or_create( project=project, user=member.user, )[1] except ProjectKey.MultipleObjectsReturned: pass
def handle(self, **options): from django.db.models import Q from sentry.constants import RESERVED_ORGANIZATION_SLUGS from sentry.models import Organization, Project, Team, ProjectKey from sentry.db.models import update from sentry.db.models.utils import slugify_instance from sentry.utils.query import RangeQuerySetWrapperWithProgressBar print("Correcting data on organizations") queryset = Organization.objects.filter(slug__isnull=True, ) for org in RangeQuerySetWrapperWithProgressBar(queryset): slugify_instance(org, org.name, RESERVED_ORGANIZATION_SLUGS) org.save() # Create teams for any projects that are missing them print("Correcting data on projects") queryset = Project.objects.filter( Q(team__isnull=True) | Q(organization__isnull=True), ).select_related('owner') for project in RangeQuerySetWrapperWithProgressBar(queryset): if not project.team: organization = Organization( name=project.name, owner=project.owner, ) slugify_instance(organization, organization.name, RESERVED_ORGANIZATION_SLUGS) organization.save() team = Team( name=project.name, owner=project.owner, oprganization=organization, ) slugify_instance(team, team.name, RESERVED_ORGANIZATION_SLUGS) team.save() update(project, organization=team.organization, team=team) # Create missing project keys print("Creating missing project keys") queryset = Team.objects.all() for team in RangeQuerySetWrapperWithProgressBar(queryset): for member in team.member_set.select_related('user'): for project in team.project_set.all(): try: created = ProjectKey.objects.get_or_create( project=project, user=member.user, )[1] except ProjectKey.MultipleObjectsReturned: pass
def save(self, *args, **kwargs): if not self.slug: slugify_instance(self, self.name, reserved=RESERVED_ORGANIZATION_SLUGS) super(Organization, self).save(*args, **kwargs)
def test_no_conflict(self): org = Organization(name="matt") slugify_instance(org, "matt") assert org.slug == "matt" assert not Organization.objects.filter(slug="matt").exists()
def save(self, *args, **kwargs): if not self.slug: slugify_instance(self, self.name, organization=self.organization) super(Team, self).save(*args, **kwargs)
def transfer_to(self, team): # NOTE: this will only work properly if the new team is in a different # org than the existing one, which is currently the only use case in # production # TODO(jess): refactor this to make it an org transfer only from sentry.models import ( Environment, EnvironmentProject, ProjectTeam, ReleaseProject, Rule, ) organization = team.organization old_org_id = self.organization_id org_changed = old_org_id != organization.id self.organization = organization try: with transaction.atomic(): self.update(organization=organization, ) except IntegrityError: slugify_instance(self, self.name, organization=organization) self.update( slug=self.slug, organization=organization, ) # Both environments and releases are bound at an organization level. # Due to this, when you transfer a project into another org, we have to # handle this behavior somehow. We really only have two options here: # * Copy over all releases/environments into the new org and handle de-duping # * Delete the bindings and let them reform with new data. # We're generally choosing to just delete the bindings since new data # flowing in will recreate links correctly. The tradeoff is that # historical data is lost, but this is a compromise we're willing to # take and a side effect of allowing this feature. There are exceptions # to this however, such as rules, which should maintain their # configuration when moved across organizations. if org_changed: for model in ReleaseProject, EnvironmentProject: model.objects.filter(project_id=self.id, ).delete() # this is getting really gross, but make sure there aren't lingering associations # with old orgs or teams ProjectTeam.objects.filter( project=self, team__organization_id=old_org_id).delete() rules_by_environment_id = defaultdict(set) for rule_id, environment_id in Rule.objects.filter( project_id=self.id, environment_id__isnull=False).values_list( 'id', 'environment_id'): rules_by_environment_id[environment_id].add(rule_id) environment_names = dict( Environment.objects.filter( id__in=rules_by_environment_id, ).values_list('id', 'name')) for environment_id, rule_ids in rules_by_environment_id.items(): Rule.objects.filter(id__in=rule_ids).update( environment_id=Environment.get_or_create( self, environment_names[environment_id], ).id, ) # ensure this actually exists in case from team was null self.add_team(team)
def test_max_length(self): org = Organization(name="matt") slugify_instance(org, "matt", max_length=2) assert org.slug == "ma", org.slug assert not Organization.objects.filter(slug="ma").exists()
def test_reserved(self): base_slug = self.organization.slug org = Organization(name='foo') slugify_instance(org, base_slug, reserved=(base_slug,)) assert not org.slug.startswith(base_slug + '-'), org.slug assert not Organization.objects.filter(slug=org.slug).exists()
def test_no_conflict(self): org = Organization(name='matt') slugify_instance(org, 'matt') assert org.slug == 'matt' assert not Organization.objects.filter(slug='matt').exists()
def transfer_to(self, team=None, organization=None): # NOTE: this will only work properly if the new team is in a different # org than the existing one, which is currently the only use case in # production # TODO(jess): refactor this to make it an org transfer only from sentry.incidents.models import AlertRule from sentry.models import ( Environment, EnvironmentProject, ProjectTeam, ReleaseProject, ReleaseProjectEnvironment, Rule, ) from sentry.models.actor import ACTOR_TYPES if organization is None: organization = team.organization old_org_id = self.organization_id org_changed = old_org_id != organization.id self.organization = organization try: with transaction.atomic(): self.update(organization=organization) except IntegrityError: slugify_instance(self, self.name, organization=organization, max_length=50) self.update(slug=self.slug, organization=organization) # Both environments and releases are bound at an organization level. # Due to this, when you transfer a project into another org, we have to # handle this behavior somehow. We really only have two options here: # * Copy over all releases/environments into the new org and handle de-duping # * Delete the bindings and let them reform with new data. # We're generally choosing to just delete the bindings since new data # flowing in will recreate links correctly. The tradeoff is that # historical data is lost, but this is a compromise we're willing to # take and a side effect of allowing this feature. There are exceptions # to this however, such as rules, which should maintain their # configuration when moved across organizations. if org_changed: for model in ReleaseProject, ReleaseProjectEnvironment, EnvironmentProject: model.objects.filter(project_id=self.id).delete() # this is getting really gross, but make sure there aren't lingering associations # with old orgs or teams ProjectTeam.objects.filter( project=self, team__organization_id=old_org_id).delete() rules_by_environment_id = defaultdict(set) for rule_id, environment_id in Rule.objects.filter( project_id=self.id, environment_id__isnull=False).values_list( "id", "environment_id"): rules_by_environment_id[environment_id].add(rule_id) environment_names = dict( Environment.objects.filter( id__in=rules_by_environment_id).values_list("id", "name")) for environment_id, rule_ids in rules_by_environment_id.items(): Rule.objects.filter(id__in=rule_ids).update( environment_id=Environment.get_or_create( self, environment_names[environment_id]).id) # ensure this actually exists in case from team was null if team is not None: self.add_team(team) # Remove alert owners not in new org alert_rules = AlertRule.objects.fetch_for_project(self).filter( owner_id__isnull=False) rules = Rule.objects.filter(owner_id__isnull=False, project=self) for rule in list(chain(alert_rules, rules)): actor = rule.owner if actor.type == ACTOR_TYPES["user"]: is_member = organization.member_set.filter( user=actor.resolve()).exists() if actor.type == ACTOR_TYPES["team"]: is_member = actor.resolve().organization_id == organization.id if not is_member: rule.update(owner=None) AlertRule.objects.fetch_for_project(self).update( organization=organization)
def save(self, *args, **kwargs): if not self.slug: slugify_instance(self, self.name, organization=self.organization) super(Project, self).save(*args, **kwargs)
def merge_to(from_org, to_org): from sentry.models import ( ApiKey, AuditLogEntry, Commit, OrganizationMember, OrganizationMemberTeam, Project, Release, ReleaseCommit, ReleaseEnvironment, ReleaseFile, Repository, Team ) for from_member in OrganizationMember.objects.filter(organization=from_org): try: to_member = OrganizationMember.objects.get( organization=to_org, user=from_member.user, ) except OrganizationMember.DoesNotExist: from_member.update(organization=to_org) to_member = from_member else: qs = OrganizationMemberTeam.objects.filter( organizationmember=from_member, is_active=True, ).select_related() for omt in qs: OrganizationMemberTeam.objects.create_or_update( organizationmember=to_member, team=omt.team, defaults={ 'is_active': True, }, ) for team in Team.objects.filter(organization=from_org): try: with transaction.atomic(): team.update(organization=to_org) except IntegrityError: slugify_instance(team, team.name, organization=to_org) team.update( organization=to_org, slug=team.slug, ) for project in Project.objects.filter(organization=from_org): try: with transaction.atomic(): project.update(organization=to_org) except IntegrityError: slugify_instance(project, project.name, organization=to_org) project.update( organization=to_org, slug=project.slug, ) # TODO(jess): update this when adding unique constraint # on version, organization for releases for release in Release.objects.filter(organization=from_org): try: to_release = Release.objects.get( version=release.version, organization=to_org ) except Release.DoesNotExist: Release.objects.filter( id=release.id ).update(organization=to_org) else: Release.merge(to_release, [release]) for model in (ApiKey, AuditLogEntry, ReleaseFile): model.objects.filter( organization=from_org, ).update(organization=to_org) for model in (Commit, ReleaseCommit, ReleaseEnvironment, Repository): model.objects.filter( organization_id=from_org.id, ).update(organization_id=to_org.id)
def test_max_length(self): org = Organization(name='matt') slugify_instance(org, 'matt', max_length=2) assert org.slug == 'ma', org.slug assert not Organization.objects.filter(slug='ma').exists()
def transfer_to(self, team=None, organization=None): # NOTE: this will only work properly if the new team is in a different # org than the existing one, which is currently the only use case in # production # TODO(jess): refactor this to make it an org transfer only from sentry.models import ( Environment, EnvironmentProject, ProjectTeam, ReleaseProject, ReleaseProjectEnvironment, Rule, ) if organization is None: organization = team.organization old_org_id = self.organization_id org_changed = old_org_id != organization.id self.organization = organization try: with transaction.atomic(): self.update( organization=organization, ) except IntegrityError: slugify_instance(self, self.name, organization=organization) self.update( slug=self.slug, organization=organization, ) # Both environments and releases are bound at an organization level. # Due to this, when you transfer a project into another org, we have to # handle this behavior somehow. We really only have two options here: # * Copy over all releases/environments into the new org and handle de-duping # * Delete the bindings and let them reform with new data. # We're generally choosing to just delete the bindings since new data # flowing in will recreate links correctly. The tradeoff is that # historical data is lost, but this is a compromise we're willing to # take and a side effect of allowing this feature. There are exceptions # to this however, such as rules, which should maintain their # configuration when moved across organizations. if org_changed: for model in ReleaseProject, ReleaseProjectEnvironment, EnvironmentProject: model.objects.filter( project_id=self.id, ).delete() # this is getting really gross, but make sure there aren't lingering associations # with old orgs or teams ProjectTeam.objects.filter(project=self, team__organization_id=old_org_id).delete() rules_by_environment_id = defaultdict(set) for rule_id, environment_id in Rule.objects.filter( project_id=self.id, environment_id__isnull=False).values_list('id', 'environment_id'): rules_by_environment_id[environment_id].add(rule_id) environment_names = dict( Environment.objects.filter( id__in=rules_by_environment_id, ).values_list('id', 'name') ) for environment_id, rule_ids in rules_by_environment_id.items(): Rule.objects.filter(id__in=rule_ids).update( environment_id=Environment.get_or_create( self, environment_names[environment_id], ).id, ) # ensure this actually exists in case from team was null if team is not None: self.add_team(team)
def merge_to(from_org, to_org): from sentry.models import ( ApiKey, AuditLogEntry, Commit, OrganizationMember, OrganizationMemberTeam, Project, Release, ReleaseCommit, ReleaseEnvironment, ReleaseFile, ReleaseHeadCommit, Repository, Team, Environment, ) for from_member in OrganizationMember.objects.filter( organization=from_org, user__isnull=False): try: to_member = OrganizationMember.objects.get( organization=to_org, user=from_member.user, ) except OrganizationMember.DoesNotExist: from_member.update(organization=to_org) to_member = from_member else: qs = OrganizationMemberTeam.objects.filter( organizationmember=from_member, is_active=True, ).select_related() for omt in qs: OrganizationMemberTeam.objects.create_or_update( organizationmember=to_member, team=omt.team, defaults={ 'is_active': True, }, ) for team in Team.objects.filter(organization=from_org): try: with transaction.atomic(): team.update(organization=to_org) except IntegrityError: slugify_instance(team, team.name, organization=to_org) team.update( organization=to_org, slug=team.slug, ) for project in Project.objects.filter(organization=from_org): try: with transaction.atomic(): project.update(organization=to_org) except IntegrityError: slugify_instance(project, project.name, organization=to_org) project.update( organization=to_org, slug=project.slug, ) # TODO(jess): update this when adding unique constraint # on version, organization for releases for release in Release.objects.filter(organization=from_org): try: to_release = Release.objects.get(version=release.version, organization=to_org) except Release.DoesNotExist: Release.objects.filter(id=release.id).update( organization=to_org) else: Release.merge(to_release, [release]) for model in (ApiKey, AuditLogEntry, ReleaseFile): model.objects.filter( organization=from_org, ).update(organization=to_org) for model in (Commit, ReleaseCommit, ReleaseEnvironment, ReleaseHeadCommit, Repository, Environment): model.objects.filter(organization_id=from_org.id, ).update( organization_id=to_org.id)
def test_conflict(self): base_slug = self.organization.slug org = Organization(name='foo') slugify_instance(org, base_slug) assert org.slug.startswith(base_slug + '-'), org.slug assert not Organization.objects.filter(slug=org.slug).exists()
def save(self, *args, **kwargs): if not self.slug: slugify_instance(self, self.name, reserved=RESERVED_TEAM_SLUGS) super(Team, self).save(*args, **kwargs)
def test_reserved(self): base_slug = self.organization.slug org = Organization(name="foo") slugify_instance(org, base_slug, reserved=(base_slug, )) assert not org.slug.startswith(base_slug + "-"), org.slug assert not Organization.objects.filter(slug=org.slug).exists()
def save(self, *args, **kwargs): if not self.slug: slugify_instance(self, self.name, team=self.team) super(Project, self).save(*args, **kwargs)
def merge_to(from_org, to_org): from sentry.models import ( ApiKey, AuditLogEntry, AuthProvider, Commit, OrganizationAvatar, OrganizationIntegration, OrganizationMember, OrganizationMemberTeam, Project, Release, ReleaseCommit, ReleaseEnvironment, ReleaseFile, ReleaseHeadCommit, Repository, Team, Environment, ) for from_member in OrganizationMember.objects.filter( organization=from_org, user__isnull=False ): logger = logging.getLogger('sentry.merge') try: to_member = OrganizationMember.objects.get( organization=to_org, user=from_member.user, ) except OrganizationMember.DoesNotExist: from_member.update(organization=to_org) to_member = from_member else: qs = OrganizationMemberTeam.objects.filter( organizationmember=from_member, is_active=True, ).select_related() for omt in qs: OrganizationMemberTeam.objects.create_or_update( organizationmember=to_member, team=omt.team, defaults={ 'is_active': True, }, ) logger.info('user.migrate', extra={ 'instance_id': from_member.id, 'new_member_id': to_member.id, 'from_organization_id': from_org.id, 'to_organization_id': to_org.id, }) for from_team in Team.objects.filter(organization=from_org): try: with transaction.atomic(): from_team.update(organization=to_org) except IntegrityError: slugify_instance(from_team, from_team.name, organization=to_org) from_team.update( organization=to_org, slug=from_team.slug, ) logger.info('team.migrate', extra={ 'instance_id': from_team.id, 'new_slug': from_team.slug, 'from_organization_id': from_org.id, 'to_organization_id': to_org.id, }) for from_project in Project.objects.filter(organization=from_org): try: with transaction.atomic(): from_project.update(organization=to_org) except IntegrityError: slugify_instance( from_project, from_project.name, organization=to_org, reserved=RESERVED_PROJECT_SLUGS) from_project.update( organization=to_org, slug=from_project.slug, ) logger.info('project.migrate', extra={ 'instance_id': from_project.id, 'new_slug': from_project.slug, 'from_organization_id': from_org.id, 'to_organization_id': to_org.id, }) # TODO(jess): update this when adding unique constraint # on version, organization for releases for from_release in Release.objects.filter(organization=from_org): try: to_release = Release.objects.get(version=from_release.version, organization=to_org) except Release.DoesNotExist: Release.objects.filter(id=from_release.id).update(organization=to_org) else: Release.merge(to_release, [from_release]) logger.info('release.migrate', extra={ 'instance_id': from_release.id, 'from_organization_id': from_org.id, 'to_organization_id': to_org.id, }) def do_update(queryset, params): model_name = queryset.model.__name__.lower() try: with transaction.atomic(): queryset.update(**params) except IntegrityError: for instance in queryset: try: with transaction.atomic(): instance.update(**params) except IntegrityError: logger.info('{}.migrate-skipped'.format(model_name), extra={ 'from_organization_id': from_org.id, 'to_organization_id': to_org.id, }) else: logger.info('{}.migrate'.format(model_name), extra={ 'instance_id': instance.id, 'from_organization_id': from_org.id, 'to_organization_id': to_org.id, }) else: logger.info('{}.migrate'.format(model_name), extra={ 'from_organization_id': from_org.id, 'to_organization_id': to_org.id, }) INST_MODEL_LIST = ( AuthProvider, ApiKey, AuditLogEntry, OrganizationAvatar, OrganizationIntegration, ReleaseEnvironment, ReleaseFile, ) ATTR_MODEL_LIST = ( Commit, ReleaseCommit, ReleaseHeadCommit, Repository, Environment, ) for model in INST_MODEL_LIST: queryset = model.objects.filter( organization=from_org, ) do_update(queryset, {'organization': to_org}) for model in ATTR_MODEL_LIST: queryset = model.objects.filter( organization_id=from_org.id, ) do_update(queryset, {'organization_id': to_org.id})
def merge_to(from_org, to_org): from sentry.models import ( ApiKey, AuditLogEntry, AuthProvider, Commit, Environment, OrganizationAvatar, OrganizationIntegration, OrganizationMember, OrganizationMemberTeam, Project, Release, ReleaseCommit, ReleaseEnvironment, ReleaseFile, ReleaseHeadCommit, Repository, Team, ) for from_member in OrganizationMember.objects.filter( organization=from_org, user__isnull=False): logger = logging.getLogger("sentry.merge") try: to_member = OrganizationMember.objects.get( organization=to_org, user=from_member.user) except OrganizationMember.DoesNotExist: from_member.update(organization=to_org) to_member = from_member else: qs = OrganizationMemberTeam.objects.filter( organizationmember=from_member, is_active=True).select_related() for omt in qs: OrganizationMemberTeam.objects.create_or_update( organizationmember=to_member, team=omt.team, defaults={"is_active": True}) logger.info( "user.migrate", extra={ "instance_id": from_member.id, "new_member_id": to_member.id, "from_organization_id": from_org.id, "to_organization_id": to_org.id, }, ) for from_team in Team.objects.filter(organization=from_org): try: with transaction.atomic(): from_team.update(organization=to_org) except IntegrityError: slugify_instance(from_team, from_team.name, organization=to_org) from_team.update(organization=to_org, slug=from_team.slug) logger.info( "team.migrate", extra={ "instance_id": from_team.id, "new_slug": from_team.slug, "from_organization_id": from_org.id, "to_organization_id": to_org.id, }, ) for from_project in Project.objects.filter(organization=from_org): try: with transaction.atomic(): from_project.update(organization=to_org) except IntegrityError: slugify_instance( from_project, from_project.name, organization=to_org, reserved=RESERVED_PROJECT_SLUGS, ) from_project.update(organization=to_org, slug=from_project.slug) logger.info( "project.migrate", extra={ "instance_id": from_project.id, "new_slug": from_project.slug, "from_organization_id": from_org.id, "to_organization_id": to_org.id, }, ) # TODO(jess): update this when adding unique constraint # on version, organization for releases for from_release in Release.objects.filter(organization=from_org): try: to_release = Release.objects.get(version=from_release.version, organization=to_org) except Release.DoesNotExist: Release.objects.filter(id=from_release.id).update( organization=to_org) else: Release.merge(to_release, [from_release]) logger.info( "release.migrate", extra={ "instance_id": from_release.id, "from_organization_id": from_org.id, "to_organization_id": to_org.id, }, ) def do_update(queryset, params): model_name = queryset.model.__name__.lower() try: with transaction.atomic(): queryset.update(**params) except IntegrityError: for instance in queryset: try: with transaction.atomic(): instance.update(**params) except IntegrityError: logger.info( f"{model_name}.migrate-skipped", extra={ "from_organization_id": from_org.id, "to_organization_id": to_org.id, }, ) else: logger.info( f"{model_name}.migrate", extra={ "instance_id": instance.id, "from_organization_id": from_org.id, "to_organization_id": to_org.id, }, ) else: logger.info( f"{model_name}.migrate", extra={ "from_organization_id": from_org.id, "to_organization_id": to_org.id }, ) INST_MODEL_LIST = ( AuthProvider, ApiKey, AuditLogEntry, OrganizationAvatar, OrganizationIntegration, ReleaseEnvironment, ReleaseFile, ) ATTR_MODEL_LIST = (Commit, ReleaseCommit, ReleaseHeadCommit, Repository, Environment) for model in INST_MODEL_LIST: queryset = model.objects.filter(organization=from_org) do_update(queryset, {"organization": to_org}) for model in ATTR_MODEL_LIST: queryset = model.objects.filter(organization_id=from_org.id) do_update(queryset, {"organization_id": to_org.id})