def upload_component_file(user, c_id):
    COMPONENT_FILES = models.COMPONENT_FILES

    component = v1_utils.verify_existence_and_get(c_id, _TABLE)
    if str(component['topic_id']) not in v1_utils.user_topic_ids(user):
        raise dci_exc.Unauthorized()

    store = dci_config.get_store('components')

    file_id = utils.gen_uuid()
    file_path = files_utils.build_file_path(component['topic_id'],
                                            c_id,
                                            file_id)
    content = files_utils.get_stream_or_content_from_request(flask.request)
    store.upload(file_path, content)
    s_file = store.head(file_path)

    values = dict.fromkeys(['md5', 'mime', 'component_id', 'name'])

    values.update({
        'id': file_id,
        'component_id': c_id,
        'name': file_id,
        'created_at': datetime.datetime.utcnow().isoformat(),
        'md5': s_file['etag'],
        'mime': s_file['content-type'],
        'size': s_file['content-length']
    })

    query = COMPONENT_FILES.insert().values(**values)

    flask.g.db_conn.execute(query)
    result = json.dumps({'component_file': values})
    return flask.Response(result, 201, content_type='application/json')
Example #2
0
def _validate_input(values, user):
    topic_id = values.pop('topic_id')
    remoteci_id = values.get('remoteci_id')

    values.update({
        'id': utils.gen_uuid(),
        'created_at': datetime.datetime.utcnow().isoformat(),
        'updated_at': datetime.datetime.utcnow().isoformat(),
        'etag': utils.gen_etag(),
        'status': 'new'
    })

    remoteci = v1_utils.verify_existence_and_get(remoteci_id, models.REMOTECIS)
    v1_utils.verify_existence_and_get(topic_id, models.TOPICS)

    # let's kill existing running jobs for the remoteci
    where_clause = sql.expression.and_(
        _TABLE.c.remoteci_id == remoteci_id,
        _TABLE.c.status.in_(('new', 'pre-run', 'running', 'post-run'))
    )
    kill_query = _TABLE .update().where(where_clause).values(status='killed')
    flask.g.db_conn.execute(kill_query)

    if remoteci['state'] != 'active':
        message = 'RemoteCI "%s" is disabled.' % remoteci_id
        raise dci_exc.DCIException(message, status_code=412)

    # The user belongs to the topic then we can start the scheduling
    v1_utils.verify_team_in_topic(user, topic_id)
    return topic_id, remoteci
Example #3
0
def upload_component_file(user, c_id):
    if not auth.is_admin(user):
        raise auth.UNAUTHORIZED

    COMPONENT_FILES = models.COMPONENT_FILES

    component = v1_utils.verify_existence_and_get(c_id, _TABLE)

    swift = dci_config.get_store('components')

    file_id = utils.gen_uuid()
    file_path = swift.build_file_path(component['topic_id'], c_id, file_id)

    swift = dci_config.get_store('components')
    swift.upload(file_path, flask.request.stream)
    s_file = swift.head(file_path)

    values = dict.fromkeys(['md5', 'mime', 'component_id', 'name'])

    values.update({
        'id': file_id,
        'component_id': c_id,
        'name': file_id,
        'created_at': datetime.datetime.utcnow().isoformat(),
        'md5': s_file['etag'],
        'mime': s_file['content-type'],
        'size': s_file['content-length']
    })

    query = COMPONENT_FILES.insert().values(**values)

    flask.g.db_conn.execute(query)
    result = json.dumps({'component_file': values})
    return flask.Response(result, 201, content_type='application/json')
Example #4
0
def insert_jobstate(user, values):
    values.update({
        'id': utils.gen_uuid(),
        'created_at': datetime.datetime.utcnow().isoformat()
    })

    query = _TABLE.insert().values(**values)

    flask.g.db_conn.execute(query)
Example #5
0
def create_new_upgrade_job_from_an_existing_job(user):
    """Create a new job in the 'next topic' of the topic of
    the provided job_id."""
    values = flask.request.json
    check_json_is_valid(upgrade_job_schema, values)

    values.update({
        'id': utils.gen_uuid(),
        'created_at': get_utc_now().isoformat(),
        'updated_at': get_utc_now().isoformat(),
        'etag': utils.gen_etag(),
        'status': 'new'
    })

    original_job_id = values.pop('job_id')
    original_job = v1_utils.verify_existence_and_get(original_job_id,
                                                     models.JOBS)
    if user.is_not_in_team(original_job['team_id']) and user.is_not_epm():
        raise dci_exc.Unauthorized()

    # get the remoteci
    remoteci_id = str(original_job['remoteci_id'])
    remoteci = v1_utils.verify_existence_and_get(remoteci_id, models.REMOTECIS)
    values.update({'remoteci_id': remoteci_id})

    # get the associated topic
    topic_id = str(original_job['topic_id'])
    topic = v1_utils.verify_existence_and_get(topic_id, models.TOPICS)

    values.update({
        'user_agent':
        flask.request.environ.get('HTTP_USER_AGENT'),
        'client_version':
        flask.request.environ.get('HTTP_CLIENT_VERSION'),
    })

    next_topic_id = topic['next_topic_id']

    if not next_topic_id:
        raise dci_exc.DCIException("topic %s does not contains a next topic" %
                                   topic_id)
    topic = v1_utils.verify_existence_and_get(next_topic_id, models.TOPICS)
    product_id = topic['product_id']

    # instantiate a new job in the next_topic_id
    # todo(yassine): make possible the upgrade to choose specific components
    values = _build_job(product_id,
                        next_topic_id,
                        remoteci, [],
                        values,
                        previous_job_id=original_job_id)

    return flask.Response(json.dumps({'job': values}),
                          201,
                          headers={'ETag': values['etag']},
                          content_type='application/json')
Example #6
0
def create_files(user):
    file_info = get_file_info_from_headers(dict(flask.request.headers))
    values = dict.fromkeys(
        ['md5', 'mime', 'jobstate_id', 'job_id', 'name', 'test_id'])
    values.update(file_info)

    if values.get('jobstate_id') is None and values.get('job_id') is None:
        raise dci_exc.DCIException('HTTP headers DCI-JOBSTATE-ID or '
                                   'DCI-JOB-ID must be specified')
    if values.get('name') is None:
        raise dci_exc.DCIException('HTTP header DCI-NAME must be specified')

    if values.get('jobstate_id') and values.get('job_id') is None:
        jobstate = v1_utils.verify_existence_and_get(values.get('jobstate_id'),
                                                     models.JOBSTATES)
        values['job_id'] = jobstate['job_id']

    job = v1_utils.verify_existence_and_get(values.get('job_id'), models.JOBS)
    if (user.is_not_in_team(job['team_id']) and user.is_read_only_user()
            and user.is_not_epm()):
        raise dci_exc.Unauthorized()

    file_id = utils.gen_uuid()
    file_path = files_utils.build_file_path(job['team_id'], values['job_id'],
                                            file_id)

    content = files_utils.get_stream_or_content_from_request(flask.request)
    store = dci_config.get_store('files')
    store.upload(file_path, content)
    s_file = store.head(file_path)

    etag = utils.gen_etag()
    values.update({
        'id': file_id,
        'created_at': datetime.datetime.utcnow().isoformat(),
        'updated_at': datetime.datetime.utcnow().isoformat(),
        'team_id': job['team_id'],
        'md5': None,
        'size': s_file['content-length'],
        'state': 'active',
        'etag': etag,
    })

    with flask.g.db_conn.begin():
        q_insert_file = _TABLE.insert().values(**values)
        flask.g.db_conn.execute(q_insert_file)
        result = json.dumps({'file': values})

        if values['mime'] == 'application/junit':
            _, junit_file = store.get(file_path)
            _process_junit_file(values, junit_file, job)

    return flask.Response(result, 201, content_type='application/json')
Example #7
0
def attach_issue(resource_id, table, user_id):
    """Attach an issue to a specific job."""

    values = schemas.issue.post(flask.request.json)

    if 'github.com' in values['url']:
        type = 'github'
    else:
        type = 'bugzilla'

    issue_id = utils.gen_uuid()
    values.update({
        'id': issue_id,
        'created_at': datetime.datetime.utcnow().isoformat(),
        'tracker': type,
    })

    # First, insert the issue if it doesn't already exist
    # in the issues table. If it already exists, ignore the
    # exceptions, and keep proceeding.
    query = _TABLE.insert().values(**values)
    try:
        flask.g.db_conn.execute(query)
    except sa_exc.IntegrityError:
        # It is not a real failure it the issue have been tried
        # to inserted a second time. As long as it is once, we are
        # good to proceed
        query = (sql.select([_TABLE]).where(_TABLE.c.url == values['url']))
        rows = list(flask.g.db_conn.execute(query))
        issue_id = rows[0][0]  # the 'id' field of the issues table.

    # Second, insert a join record in the JOIN_JOBS_ISSUES or
    # JOIN_COMPONENTS_ISSUES database.
    if table.name == 'jobs':
        join_table = models.JOIN_JOBS_ISSUES
    else:
        join_table = models.JOIN_COMPONENTS_ISSUES

    key = '%s_id' % table.name[0:-1]
    query = join_table.insert().values({
        'user_id': user_id,
        'issue_id': issue_id,
        key: resource_id
    })

    try:
        flask.g.db_conn.execute(query)
    except sa_exc.IntegrityError:
        raise dci_exc.DCICreationConflict(join_table.name,
                                          '%s, issue_id' % key)

    result = json.dumps({'issue': values})
    return flask.Response(result, 201, content_type='application/json')
Example #8
0
def upgrade_jobs(user):
    values = schemas.job_upgrade.post(flask.request.json)

    values.update({
        'id': utils.gen_uuid(),
        'created_at': datetime.datetime.utcnow().isoformat(),
        'updated_at': datetime.datetime.utcnow().isoformat(),
        'etag': utils.gen_etag(),
        'status': 'new'
    })

    original_job_id = values.pop('job_id')
    original_job = v1_utils.verify_existence_and_get(original_job_id,
                                                     models.JOBS)
    v1_utils.verify_user_in_team(user, original_job['team_id'])

    # get the remoteci
    remoteci_id = str(original_job['remoteci_id'])
    remoteci = v1_utils.verify_existence_and_get(remoteci_id,
                                                 models.REMOTECIS)
    values.update({'remoteci_id': remoteci_id})

    # get the jobdefinition
    jobdefinition_id = str(original_job['jobdefinition_id'])
    jobdefinition = v1_utils.verify_existence_and_get(jobdefinition_id,
                                                      models.JOBDEFINITIONS)

    # get the associated topic
    topic_id = str(jobdefinition['topic_id'])
    topic = v1_utils.verify_existence_and_get(topic_id, models.TOPICS)

    values.update({
        'user_agent': flask.request.environ.get('HTTP_USER_AGENT'),
        'client_version': flask.request.environ.get(
            'HTTP_CLIENT_VERSION'
        ),
    })

    next_topic_id = topic['next_topic']

    if not next_topic_id:
        raise dci_exc.DCIException(
            "topic %s does not contains a next topic" % topic_id)

    # instantiate a new job in the next_topic_id
    values = _build_new_template(next_topic_id, remoteci, values,
                                 previous_job_id=original_job_id)

    return flask.Response(json.dumps({'job': values}), 201,
                          headers={'ETag': values['etag']},
                          content_type='application/json')
Example #9
0
def create_new_update_job_from_an_existing_job(user, job_id):
    """Create a new job in the same topic as the job_id provided and
    associate the latest components of this topic."""

    values = {
        'id': utils.gen_uuid(),
        'created_at': get_utc_now().isoformat(),
        'updated_at': get_utc_now().isoformat(),
        'etag': utils.gen_etag(),
        'status': 'new'
    }

    original_job_id = job_id
    original_job = v1_utils.verify_existence_and_get(original_job_id,
                                                     models.JOBS)

    if user.is_not_in_team(original_job['team_id']) and user.is_not_epm():
        raise dci_exc.Unauthorized()

    # get the remoteci
    remoteci_id = str(original_job['remoteci_id'])
    remoteci = v1_utils.verify_existence_and_get(remoteci_id, models.REMOTECIS)
    values.update({'remoteci_id': remoteci_id})

    # get the associated topic
    topic_id = str(original_job['topic_id'])
    topic = v1_utils.verify_existence_and_get(topic_id, models.TOPICS)
    product_id = topic['product_id']
    v1_utils.verify_existence_and_get(topic_id, models.TOPICS)

    values.update({
        'user_agent':
        flask.request.environ.get('HTTP_USER_AGENT'),
        'client_version':
        flask.request.environ.get('HTTP_CLIENT_VERSION'),
    })

    values = _build_job(product_id,
                        topic_id,
                        remoteci, [],
                        values,
                        update_previous_job_id=original_job_id)

    return flask.Response(json.dumps({'job': values}),
                          201,
                          headers={'ETag': values['etag']},
                          content_type='application/json')
Example #10
0
def common_values_dict():
    """Build a basic values object used in every create method.

       All our resources contain a same subset of value. Instead of
       redoing this code everytime, this method ensures it is done only at
       one place.
    """
    now = datetime.datetime.utcnow().isoformat()
    etag = utils.gen_etag()
    values = {
        'id': utils.gen_uuid(),
        'created_at': now,
        'updated_at': now,
        'etag': etag
    }

    return values
Example #11
0
def common_values_dict(user):
    """Build a basic values object used in every create method.

       All our resources contain a same subset of value. Instead of
       redoing this code everytime, this method ensures it is done only at
       one place.
    """

    created_at, updated_at = utils.get_dates(user)
    etag = utils.gen_etag()
    values = {
        'id': utils.gen_uuid(),
        'created_at': created_at,
        'updated_at': updated_at,
        'etag': etag
    }

    return values
def upgrade():
    op.add_column('components',
                  sa.Column('topic_id', sa.String(36),
                            sa.ForeignKey('topics.id', ondelete="CASCADE"),
                            nullable=True))
    op.add_column('tests',
                  sa.Column('topic_id', sa.String(36),
                            sa.ForeignKey('topics.id', ondelete="CASCADE"),
                            nullable=True))
    op.add_column('jobdefinitions',
                  sa.Column('topic_id', sa.String(36),
                            sa.ForeignKey('topics.id', ondelete="CASCADE"),
                            nullable=True))
    db_conn = op.get_bind()

    # Create a default topic
    topic_id = utils.gen_uuid()
    topic_values = {
        'id': topic_id,
        'created_at': datetime.datetime.utcnow().isoformat(),
        'updated_at': datetime.datetime.utcnow().isoformat(),
        'etag': utils.gen_etag(),
        'name': 'default'
    }
    db_conn.execute(TOPICS.insert().values(**topic_values))

    # Adds all components, jobdefinitions and tests to the default topics
    values = {'topic_id': topic_id}
    db_conn.execute(COMPONENTS.update().values(**values))
    db_conn.execute(models.JOBDEFINITIONS.update().values(**values))
    db_conn.execute(TESTS.update().values(**values))

    # Adds all teams to the default topics
    all_teams = db_conn.execute(TEAMS.select()).fetchall()

    teams_topic = [{'topic_id': topic_id, 'team_id': team['id']}
                   for team in all_teams]
    if teams_topic:
        db_conn.execute(models.JOINS_TOPICS_TEAMS.insert(), teams_topic)
Example #13
0
def _process_junit_file(values, junit_file, job):
    jsonunit = tsfm.junit2dict(junit_file)
    previous_jsonunit = _get_previous_jsonunit(job, values['name'])

    jsonunit = _compute_regressions_successfix(jsonunit, previous_jsonunit)
    jsonunit = _compute_known_tests_cases(jsonunit, job)

    query = models.TESTS_RESULTS.insert().values({
        'id':
        utils.gen_uuid(),
        'created_at':
        values['created_at'],
        'updated_at':
        datetime.datetime.utcnow().isoformat(),
        'file_id':
        values['id'],
        'job_id':
        job['id'],
        'name':
        values['name'],
        'success':
        jsonunit['success'],
        'failures':
        jsonunit['failures'],
        'errors':
        jsonunit['errors'],
        'regressions':
        jsonunit['regressions'],
        'successfixes':
        jsonunit['successfixes'],
        'skips':
        jsonunit['skips'],
        'total':
        jsonunit['total'],
        'time':
        jsonunit['time']
    })

    flask.g.db_conn.execute(query)
Example #14
0
def schedule_jobs(user):
    """Dispatch jobs to remotecis.

    The remoteci can use this method to request a new job.

    Before a job is dispatched, the server will flag as 'killed' all the
    running jobs that were associated with the remoteci. This is because they
    will never be finished.
    """
    values = flask.request.json
    check_json_is_valid(schedule_job_schema, values)
    values.update({
        'id':
        utils.gen_uuid(),
        'created_at':
        get_utc_now().isoformat(),
        'updated_at':
        get_utc_now().isoformat(),
        'etag':
        utils.gen_etag(),
        'status':
        'new',
        'remoteci_id':
        user.id,
        'duration':
        0,
        'user_agent':
        flask.request.environ.get('HTTP_USER_AGENT'),
        'client_version':
        flask.request.environ.get('HTTP_CLIENT_VERSION'),
    })
    topic_id = values.pop('topic_id')
    dry_run = values.pop('dry_run')
    if dry_run:
        component_types = components.get_component_types_from_topic(topic_id)
        _components = components.get_last_components_by_type(
            component_types, topic_id)
        return flask.Response(json.dumps({
            'components': _components,
            'job': None
        }),
                              201,
                              content_type='application/json')

    # check remoteci
    remoteci = v1_utils.verify_existence_and_get(user.id, models.REMOTECIS)
    if remoteci['state'] != 'active':
        message = 'RemoteCI "%s" is disabled.' % remoteci['id']
        raise dci_exc.DCIException(message, status_code=412)

    # check primary topic
    topic = v1_utils.verify_existence_and_get(topic_id, models.TOPICS)
    product_id = topic['product_id']
    if topic['state'] != 'active':
        msg = 'Topic %s:%s not active.' % (topic_id, topic['name'])
        raise dci_exc.DCIException(msg, status_code=412)
    export_control.verify_access_to_topic(user, topic)

    # check secondary topic
    topic_id_secondary = values.pop('topic_id_secondary')
    if topic_id_secondary:
        topic_secondary = v1_utils.verify_existence_and_get(
            topic_id_secondary, models.TOPICS)
        if topic_secondary['state'] != 'active':
            msg = 'Topic %s:%s not active.' % (topic_id_secondary,
                                               topic['name'])
            raise dci_exc.DCIException(msg, status_code=412)
        export_control.verify_access_to_topic(user, topic_secondary)

    remotecis.kill_existing_jobs(remoteci['id'])

    components_ids = values.pop('components_ids')
    values = _build_job(product_id,
                        topic_id,
                        remoteci,
                        components_ids,
                        values,
                        topic_id_secondary=topic_id_secondary)

    return flask.Response(json.dumps({'job': values}),
                          201,
                          headers={'ETag': values['etag']},
                          content_type='application/json')
Example #15
0
def create_files(user):
    file_info = get_file_info_from_headers(dict(flask.request.headers))
    swift = dci_config.get_store('files')

    values = dict.fromkeys(
        ['md5', 'mime', 'jobstate_id', 'job_id', 'name', 'test_id'])
    values.update(file_info)

    if values.get('jobstate_id') is None and values.get('job_id') is None:
        raise dci_exc.DCIException('HTTP headers DCI-JOBSTATE-ID or '
                                   'DCI-JOB-ID must be specified')
    if values.get('name') is None:
        raise dci_exc.DCIException('HTTP header DCI-NAME must be specified')

    if values['jobstate_id']:
        query = v1_utils.QueryBuilder(models.JOBSTATES)
        query.add_extra_condition(
            models.JOBSTATES.c.id == values['jobstate_id'])
        row = query.execute(fetchone=True)
        if row is None:
            raise dci_exc.DCINotFound('Jobstate', values['jobstate_id'])
        values['job_id'] = row['jobstates_job_id']

    query = v1_utils.QueryBuilder(models.JOBS)
    if not auth.is_admin(user):
        query.add_extra_condition(models.JOBS.c.team_id == user['team_id'])
    query.add_extra_condition(models.JOBS.c.id == values['job_id'])
    row = query.execute(fetchone=True)
    if row is None:
        raise dci_exc.DCINotFound('Job', values['job_id'])

    file_id = utils.gen_uuid()
    # ensure the directory which will contains the file actually exist

    file_path = swift.build_file_path(user['team_id'], values['job_id'],
                                      file_id)

    content = files.get_stream_or_content_from_request(flask.request)
    swift.upload(file_path, content)
    s_file = swift.head(file_path)

    etag = utils.gen_etag()
    values.update({
        'id': file_id,
        'created_at': datetime.datetime.utcnow().isoformat(),
        'updated_at': datetime.datetime.utcnow().isoformat(),
        'team_id': user['team_id'],
        'md5': None,
        'size': s_file['content-length'],
        'state': 'active',
        'etag': etag,
    })

    query = _TABLE.insert().values(**values)

    with flask.g.db_conn.begin():

        flask.g.db_conn.execute(query)
        result = json.dumps({'file': values})

        if values['mime'] == 'application/junit':
            _, file_descriptor = swift.get(file_path)
            junit = tsfm.junit2dict(file_descriptor.read())
            query = models.TESTS_RESULTS.insert().values({
                'id':
                utils.gen_uuid(),
                'created_at':
                values['created_at'],
                'updated_at':
                datetime.datetime.utcnow().isoformat(),
                'file_id':
                file_id,
                'job_id':
                values['job_id'],
                'name':
                values['name'],
                'success':
                junit['success'],
                'failures':
                junit['failures'],
                'errors':
                junit['errors'],
                'skips':
                junit['skips'],
                'total':
                junit['total'],
                'time':
                junit['time']
            })
            flask.g.db_conn.execute(query)
        files_events.create_event(file_id, models.FILES_CREATE)

    return flask.Response(result, 201, content_type='application/json')
def upgrade():
    op.create_table(
        'components',
        sa.Column('id',
                  sa.String(36),
                  primary_key=True,
                  default=utils.gen_uuid),
        sa.Column('created_at',
                  sa.DateTime(),
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('updated_at',
                  sa.DateTime(),
                  onupdate=datetime.datetime.utcnow,
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('etag',
                  sa.String(40),
                  nullable=False,
                  default=utils.gen_etag,
                  onupdate=utils.gen_etag),
        sa.Column('name', sa.String(255), unique=True, nullable=False),
        sa.Column('type', sa.String(255), nullable=False),
        sa.Column('canonical_project_name', sa.String),
        sa.Column('data', sa_utils.JSONType), sa.Column('sha', sa.Text),
        sa.Column('title', sa.Text), sa.Column('message', sa.Text),
        sa.Column('url', sa.Text), sa.Column('git', sa.Text),
        sa.Column('ref', sa.Text))

    op.create_table(
        'tests',
        sa.Column('id',
                  sa.String(36),
                  primary_key=True,
                  default=utils.gen_uuid),
        sa.Column('created_at',
                  sa.DateTime(),
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('updated_at',
                  sa.DateTime(),
                  onupdate=datetime.datetime.utcnow,
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('name', sa.String(255), nullable=False, unique=True),
        sa.Column('etag',
                  sa.String(40),
                  nullable=False,
                  default=utils.gen_etag,
                  onupdate=utils.gen_etag), sa.Column('data',
                                                      sa_utils.JSONType))

    op.create_table(
        'jobdefinitions',
        sa.Column('id',
                  sa.String(36),
                  primary_key=True,
                  default=utils.gen_uuid),
        sa.Column('created_at',
                  sa.DateTime(),
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('updated_at',
                  sa.DateTime(),
                  onupdate=datetime.datetime.utcnow,
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('etag',
                  sa.String(40),
                  nullable=False,
                  default=utils.gen_etag,
                  onupdate=utils.gen_etag), sa.Column('name', sa.String(255)),
        sa.Column('priority', sa.Integer, default=0),
        sa.Column('test_id',
                  sa.String(36),
                  sa.ForeignKey('tests.id', ondelete="CASCADE"),
                  nullable=False))

    op.create_table(
        'jobdefinition_components',
        sa.Column('id',
                  sa.String(36),
                  primary_key=True,
                  default=utils.gen_uuid),
        sa.Column('created_at',
                  sa.DateTime(),
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('updated_at',
                  sa.DateTime(),
                  onupdate=datetime.datetime.utcnow,
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('etag',
                  sa.String(40),
                  nullable=False,
                  default=utils.gen_etag,
                  onupdate=utils.gen_etag),
        sa.Column('component_id',
                  sa.String(36),
                  sa.ForeignKey('components.id', ondelete="CASCADE"),
                  nullable=False),
        sa.Column('jobdefinition_id',
                  sa.String(36),
                  sa.ForeignKey('jobdefinitions.id', ondelete="CASCADE"),
                  nullable=False),
        sa.UniqueConstraint('component_id', 'jobdefinition_id'))

    op.create_table(
        'teams',
        sa.Column('id',
                  sa.String(36),
                  primary_key=True,
                  default=utils.gen_uuid),
        sa.Column('created_at',
                  sa.DateTime(),
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('updated_at',
                  sa.DateTime(),
                  onupdate=datetime.datetime.utcnow,
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('etag',
                  sa.String(40),
                  nullable=False,
                  default=utils.gen_etag,
                  onupdate=utils.gen_etag),
        sa.Column('name', sa.String(255), unique=True, nullable=False))

    op.create_table(
        'remotecis',
        sa.Column('id',
                  sa.String(36),
                  primary_key=True,
                  default=utils.gen_uuid),
        sa.Column('created_at',
                  sa.DateTime(),
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('updated_at',
                  sa.DateTime(),
                  onupdate=datetime.datetime.utcnow,
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('etag',
                  sa.String(40),
                  nullable=False,
                  default=utils.gen_etag,
                  onupdate=utils.gen_etag),
        sa.Column('name', sa.String(255), unique=True),
        sa.Column('data', sa_utils.JSONType),
        sa.Column('active', sa.BOOLEAN, default=True),
        sa.Column('team_id',
                  sa.String(36),
                  sa.ForeignKey('teams.id', ondelete="CASCADE"),
                  nullable=False))

    op.create_table(
        'jobs',
        sa.Column('id',
                  sa.String(36),
                  primary_key=True,
                  default=utils.gen_uuid),
        sa.Column('created_at',
                  sa.DateTime(),
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('updated_at',
                  sa.DateTime(),
                  onupdate=datetime.datetime.utcnow,
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('etag',
                  sa.String(40),
                  nullable=False,
                  default=utils.gen_etag,
                  onupdate=utils.gen_etag),
        sa.Column('recheck', sa.Boolean, default=False),
        # new, pre-run, running, post-run, success, failure
        sa.Column('status', sa.String(255), default='new'),
        sa.Column('jobdefinition_id',
                  sa.String(36),
                  sa.ForeignKey('jobdefinitions.id', ondelete="CASCADE"),
                  nullable=False),
        sa.Column('remoteci_id',
                  sa.String(36),
                  sa.ForeignKey('remotecis.id', ondelete="CASCADE"),
                  nullable=False),
        sa.Column('team_id',
                  sa.String(36),
                  sa.ForeignKey('teams.id', ondelete="CASCADE"),
                  nullable=False))

    op.create_table(
        'jobstates',
        sa.Column('id',
                  sa.String(36),
                  primary_key=True,
                  default=utils.gen_uuid),
        sa.Column('created_at',
                  sa.DateTime(),
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('updated_at',
                  sa.DateTime(),
                  onupdate=datetime.datetime.utcnow,
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('etag',
                  sa.String(40),
                  nullable=False,
                  default=utils.gen_etag,
                  onupdate=utils.gen_etag),
        # new, pre-run, running, post-run, success, failure
        sa.Column('status', sa.String(255), nullable=False),
        sa.Column('comment', sa.Text),
        sa.Column('job_id',
                  sa.String(36),
                  sa.ForeignKey('jobs.id', ondelete="CASCADE"),
                  nullable=False),
        sa.Column('team_id',
                  sa.String(36),
                  sa.ForeignKey('teams.id', ondelete="CASCADE"),
                  nullable=False))

    op.create_table(
        'files',
        sa.Column('id',
                  sa.String(36),
                  primary_key=True,
                  default=utils.gen_uuid),
        sa.Column('created_at',
                  sa.DateTime(),
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('updated_at',
                  sa.DateTime(),
                  onupdate=datetime.datetime.utcnow,
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('etag',
                  sa.String(40),
                  nullable=False,
                  default=utils.gen_etag,
                  onupdate=utils.gen_etag),
        sa.Column('name', sa.String(255), nullable=False),
        sa.Column('content', sa.Text, nullable=False),
        sa.Column('mime', sa.String), sa.Column('md5', sa.String(32)),
        sa.Column('jobstate_id',
                  sa.String(36),
                  sa.ForeignKey('jobstates.id', ondelete="CASCADE"),
                  nullable=False),
        sa.Column('team_id',
                  sa.String(36),
                  sa.ForeignKey('teams.id', ondelete="CASCADE"),
                  nullable=False))

    op.create_table(
        'users',
        sa.Column('id',
                  sa.String(36),
                  primary_key=True,
                  default=utils.gen_uuid),
        sa.Column('created_at',
                  sa.DateTime(),
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('updated_at',
                  sa.DateTime(),
                  onupdate=datetime.datetime.utcnow,
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('etag',
                  sa.String(40),
                  nullable=False,
                  default=utils.gen_etag,
                  onupdate=utils.gen_etag),
        sa.Column('name', sa.String(255), unique=True, nullable=False),
        sa.Column('password', sa.Text, nullable=False),
        sa.Column('role', sa.String(255), default='user', nullable=False),
        sa.Column('team_id',
                  sa.String(36),
                  sa.ForeignKey('teams.id', ondelete="CASCADE"),
                  nullable=False))

    op.create_table(
        'user_remotecis',
        sa.Column('id',
                  sa.String(36),
                  primary_key=True,
                  default=utils.gen_uuid),
        sa.Column('created_at',
                  sa.DateTime(),
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('updated_at',
                  sa.DateTime(),
                  onupdate=datetime.datetime.utcnow,
                  default=datetime.datetime.utcnow,
                  nullable=False),
        sa.Column('etag',
                  sa.String(40),
                  nullable=False,
                  default=utils.gen_etag,
                  onupdate=utils.gen_etag),
        sa.Column('user_id',
                  sa.String(36),
                  sa.ForeignKey('users.id', ondelete="CASCADE"),
                  nullable=False),
        sa.Column('remoteci_id',
                  sa.String(36),
                  sa.ForeignKey('remotecis.id', ondelete="CASCADE"),
                  nullable=False), sa.UniqueConstraint('user_id',
                                                       'remoteci_id'))

    db_conn = op.get_bind()
    team_id = utils.gen_uuid()
    team_values = {
        'id': team_id,
        'created_at': datetime.datetime.utcnow().isoformat(),
        'updated_at': datetime.datetime.utcnow().isoformat(),
        'etag': utils.gen_etag(),
        'name': 'admin'
    }
    db_conn.execute(TEAMS.insert().values(**team_values))

    user_id = utils.gen_uuid()
    user_values = {
        'id': user_id,
        'created_at': datetime.datetime.utcnow().isoformat(),
        'updated_at': datetime.datetime.utcnow().isoformat(),
        'etag': utils.gen_etag(),
        'name': 'admin',
        'role': 'admin',
        'team_id': team_id,
        'password': auth.hash_password('admin'),
    }
    db_conn.execute(USERS.insert().values(**user_values))
Example #17
0
def upgrade():
    op.add_column('users', sa.Column('role_id', pg.UUID(as_uuid=True),
                                     sa.ForeignKey('roles.id',
                                                   ondelete='SET NULL')))

    db_conn = op.get_bind()

    team_admin_id = str(
        db_conn.execute(
            TEAMS.select().where(TEAMS.c.name == 'admin')
        ).fetchone()['id']
    )

    super_admin_role_id = utils.gen_uuid()
    super_admin_role = {
        'id': super_admin_role_id,
        'created_at': datetime.datetime.utcnow().isoformat(),
        'updated_at': datetime.datetime.utcnow().isoformat(),
        'etag': utils.gen_etag(),
        'name': 'Super Admin',
        'label': 'SUPER_ADMIN',
        'description': 'Admin of the platform',
    }

    admin_role_id = utils.gen_uuid()
    admin_role = {
        'id': admin_role_id,
        'created_at': datetime.datetime.utcnow().isoformat(),
        'updated_at': datetime.datetime.utcnow().isoformat(),
        'etag': utils.gen_etag(),
        'name': 'Admin',
        'label': 'ADMIN',
        'description': 'Admin of a team',
    }

    user_role_id = utils.gen_uuid()
    user_role = {
        'id': user_role_id,
        'created_at': datetime.datetime.utcnow().isoformat(),
        'updated_at': datetime.datetime.utcnow().isoformat(),
        'etag': utils.gen_etag(),
        'name': 'User',
        'label': 'USER',
        'description': 'Regular User',
    }

    db_conn.execute(ROLES.insert().values(**super_admin_role))
    db_conn.execute(ROLES.insert().values(**admin_role))
    db_conn.execute(ROLES.insert().values(**user_role))

    db_conn.execute(
        USERS.update().
        where(sql.and_(USERS.c.role == 'admin',
                       USERS.c.team_id == team_admin_id)).
        values(role_id=super_admin_role_id)
    )
    db_conn.execute(
        USERS.update().
        where(sql.and_(USERS.c.role == 'admin',
                       USERS.c.team_id != team_admin_id)).
        values(role_id=admin_role_id)
    )
    db_conn.execute(
        USERS.update().where(USERS.c.role == 'user').
        values(role_id=user_role_id)
    )