Пример #1
0
def _delete_user_linked_data(user):
  if user.organization:
    # Delete the organization's teams.
    with db_transaction():
      for team in Team.select().where(Team.organization == user):
        team.delete_instance(recursive=True)

    # Delete any OAuth approvals and tokens associated with the user.
    with db_transaction():
      for app in OAuthApplication.select().where(OAuthApplication.organization == user):
        app.delete_instance(recursive=True)
  else:
    # Remove the user from any teams in which they are a member.
    TeamMember.delete().where(TeamMember.user == user).execute()

  # Delete any repository buildtriggers where the user is the connected user.
  with db_transaction():
    triggers = RepositoryBuildTrigger.select().where(RepositoryBuildTrigger.connected_user == user)
    for trigger in triggers:
      trigger.delete_instance(recursive=True, delete_nullable=False)

  # Delete any mirrors with robots owned by this user.
  with db_transaction():
    robots = list(list_namespace_robots(user.username))
    RepoMirrorConfig.delete().where(RepoMirrorConfig.internal_robot << robots).execute()

  # Delete any robots owned by this user.
  with db_transaction():
    robots = list(list_namespace_robots(user.username))
    for robot in robots:
      robot.delete_instance(recursive=True, delete_nullable=True)

  # Null out any service key approvals. We technically lose information here, but its better than
  # falling and only occurs if a superuser is being deleted.
  ServiceKeyApproval.update(approver=None).where(ServiceKeyApproval.approver == user).execute()
Пример #2
0
def test_update_trigger_disable_status(starting_failure_count,
                                       starting_error_count, status,
                                       expected_reason, initialized_db):
    test_config = {
        "SUCCESSIVE_TRIGGER_FAILURE_DISABLE_THRESHOLD":
        TEST_FAIL_THRESHOLD,
        "SUCCESSIVE_TRIGGER_INTERNAL_ERROR_DISABLE_THRESHOLD":
        TEST_INTERNAL_ERROR_THRESHOLD,
    }

    trigger = model.build.list_build_triggers("devtable", "building")[0]
    trigger.successive_failure_count = starting_failure_count
    trigger.successive_internal_error_count = starting_error_count
    trigger.enabled = True
    trigger.save()

    with patch("data.model.config.app_config", test_config):
        update_trigger_disable_status(trigger, status)
        updated_trigger = RepositoryBuildTrigger.get(uuid=trigger.uuid)

        assert updated_trigger.enabled == (expected_reason is None)

        if expected_reason is not None:
            assert updated_trigger.disabled_reason.name == expected_reason
        else:
            assert updated_trigger.disabled_reason is None
            assert updated_trigger.successive_failure_count == 0
            assert updated_trigger.successive_internal_error_count == 0
Пример #3
0
def run_branchregex_migration():
    encountered = set()
    while True:
        found = list(
            RepositoryBuildTrigger.select().where(
                RepositoryBuildTrigger.config ** "%branch_regex%",
                ~(RepositoryBuildTrigger.config ** "%branchtag_regex%"),
            )
        )
        found = [f for f in found if not f.uuid in encountered]

        if not found:
            logger.debug("No additional records found")
            return

        logger.debug("Found %s records to be changed", len(found))
        for trigger in found:
            encountered.add(trigger.uuid)

            try:
                config = json.loads(trigger.config)
            except:
                logging.error("Cannot parse config for trigger %s", trigger.uuid)
                continue

            logger.debug("Checking trigger %s", trigger.uuid)
            existing_regex = config["branch_regex"]
            logger.debug("Found branch regex '%s'", existing_regex)

            sub_regex = existing_regex.split("|")
            new_regex = "|".join(["heads/" + sub for sub in sub_regex])
            config["branchtag_regex"] = new_regex

            logger.debug("Updating to branchtag regex '%s'", new_regex)
            update_build_trigger(trigger, config)
Пример #4
0
def list_build_triggers(namespace_name, repository_name):
    return (RepositoryBuildTrigger.select(
        RepositoryBuildTrigger, BuildTriggerService,
        Repository).join(BuildTriggerService).switch(
            RepositoryBuildTrigger).join(Repository).join(
                Namespace,
                on=(Repository.namespace_user == Namespace.id)).where(
                    Namespace.username == namespace_name,
                    Repository.name == repository_name))
Пример #5
0
def get_build_trigger(trigger_uuid):
    try:
        return (
            RepositoryBuildTrigger.select(
                RepositoryBuildTrigger, BuildTriggerService, Repository,
                Namespace).join(BuildTriggerService).switch(
                    RepositoryBuildTrigger).join(Repository).join(
                        Namespace,
                        on=(Repository.namespace_user == Namespace.id)).
            switch(RepositoryBuildTrigger).join(
                User,
                on=(RepositoryBuildTrigger.connected_user == User.id)).where(
                    RepositoryBuildTrigger.uuid == trigger_uuid).get())
    except RepositoryBuildTrigger.DoesNotExist:
        msg = "No build trigger with uuid: %s" % trigger_uuid
        raise InvalidBuildTriggerException(msg)
Пример #6
0
def create_build_trigger(repo,
                         service_name,
                         auth_token,
                         user,
                         pull_robot=None,
                         config=None):
    service = BuildTriggerService.get(name=service_name)
    secure_auth_token = DecryptedValue(auth_token) if auth_token else None
    trigger = RepositoryBuildTrigger.create(
        repository=repo,
        service=service,
        secure_auth_token=secure_auth_token,
        connected_user=user,
        pull_robot=pull_robot,
        config=json.dumps(config or {}),
    )
    return trigger
Пример #7
0
def update_trigger_disable_status(trigger, final_phase):
    """
    Updates the disable status of the given build trigger.

    If the build trigger had a failure, then the counter is increased and, if we've reached the
    limit, the trigger is automatically disabled. Otherwise, if the trigger succeeded, it's counter
    is reset. This ensures that triggers that continue to error are eventually automatically
    disabled.
    """
    with db_transaction():
        try:
            trigger = RepositoryBuildTrigger.get(id=trigger.id)
        except RepositoryBuildTrigger.DoesNotExist:
            # Already deleted.
            return

        # If the build completed successfully, then reset the successive counters.
        if final_phase == BUILD_PHASE.COMPLETE:
            trigger.successive_failure_count = 0
            trigger.successive_internal_error_count = 0
            trigger.save()
            return

        # Otherwise, increment the counters and check for trigger disable.
        if final_phase == BUILD_PHASE.ERROR:
            trigger.successive_failure_count = trigger.successive_failure_count + 1
            trigger.successive_internal_error_count = 0
        elif final_phase == BUILD_PHASE.INTERNAL_ERROR:
            trigger.successive_internal_error_count = trigger.successive_internal_error_count + 1

        # Check if we need to disable the trigger.
        failure_threshold = config.app_config.get(
            "SUCCESSIVE_TRIGGER_FAILURE_DISABLE_THRESHOLD")
        error_threshold = config.app_config.get(
            "SUCCESSIVE_TRIGGER_INTERNAL_ERROR_DISABLE_THRESHOLD")

        if failure_threshold and trigger.successive_failure_count >= failure_threshold:
            toggle_build_trigger(trigger, False,
                                 TRIGGER_DISABLE_REASON.BUILD_FALURES)
        elif error_threshold and trigger.successive_internal_error_count >= error_threshold:
            toggle_build_trigger(trigger, False,
                                 TRIGGER_DISABLE_REASON.INTERNAL_ERRORS)
        else:
            # Save the trigger changes.
            trigger.save()
Пример #8
0
def create_build_trigger(repo, service_name, auth_token, user, pull_robot=None, config=None):
    service = BuildTriggerService.get(name=service_name)

    # TODO(remove-unenc): Remove legacy field.
    old_auth_token = None
    if ActiveDataMigration.has_flag(ERTMigrationFlags.WRITE_OLD_FIELDS):
        old_auth_token = auth_token

    secure_auth_token = DecryptedValue(auth_token) if auth_token else None
    trigger = RepositoryBuildTrigger.create(
        repository=repo,
        service=service,
        auth_token=old_auth_token,
        secure_auth_token=secure_auth_token,
        connected_user=user,
        pull_robot=pull_robot,
        config=json.dumps(config or {}),
    )
    return trigger
Пример #9
0
def ask_disable_namespace(username, queue_name):
    user = model.user.get_namespace_user(username)
    if user is None:
        raise Exception("Unknown user or organization %s" % username)

    if not user.enabled:
        print("NOTE: Namespace %s is already disabled" % username)

    queue_prefix = "%s/%s/%%" % (queue_name, username)
    existing_queue_item_count = (QueueItem.select().where(
        QueueItem.queue_name**queue_prefix).where(
            QueueItem.available == 1,
            QueueItem.retries_remaining > 0,
            QueueItem.processing_expires > datetime.now(),
        ).count())

    repository_trigger_count = (
        RepositoryBuildTrigger.select().join(Repository).where(
            Repository.namespace_user == user).count())

    print("=============================================")
    print("For namespace %s" % username)
    print("=============================================")

    print("User %s has email address %s" % (username, user.email))
    print("User %s has %s queued builds in their namespace" %
          (username, existing_queue_item_count))
    print("User %s has %s build triggers in their namespace" %
          (username, repository_trigger_count))

    confirm_msg = (
        "Would you like to disable this user and delete their triggers and builds? [y/N]> "
    )
    letter = str(input(confirm_msg))
    if letter.lower() != "y":
        print("Action canceled")
        return

    print("=============================================")

    triggers = []
    count_removed = 0
    with db_transaction():
        user.enabled = False
        user.save()

        repositories_query = Repository.select().where(
            Repository.namespace_user == user)
        if len(repositories_query.clone()):
            builds = list(RepositoryBuild.select().where(
                RepositoryBuild.repository << list(repositories_query)))

            triggers = list(RepositoryBuildTrigger.select().where(
                RepositoryBuildTrigger.repository << list(repositories_query)))

            mirrors = list(RepoMirrorConfig.select().where(
                RepoMirrorConfig.repository << list(repositories_query)))

            # Delete all builds for the user's repositories.
            if builds:
                RepositoryBuild.delete().where(
                    RepositoryBuild.id << builds).execute()

            # Delete all build triggers for the user's repositories.
            if triggers:
                RepositoryBuildTrigger.delete().where(
                    RepositoryBuildTrigger.id << triggers).execute()

            # Delete all mirrors for the user's repositories.
            if mirrors:
                RepoMirrorConfig.delete().where(
                    RepoMirrorConfig.id << mirrors).execute()

            # Delete all queue items for the user's namespace.
            dockerfile_build_queue = WorkQueue(queue_name,
                                               tf,
                                               has_namespace=True)
            count_removed = dockerfile_build_queue.delete_namespaced_items(
                user.username)

    info = (user.username, len(triggers), count_removed, len(mirrors))
    print(
        "Namespace %s disabled, %s triggers deleted, %s queued builds removed, %s mirrors deleted"
        % info)
    return user