Exemple #1
0
module.exports = () => ({
    method: 'DELETE',
    path: '/commands/{namespace}/{name}',
    config: {
        description: 'Delete a command',
        notes: 'Returns null if successful',
        tags: ['api', 'commands'],
        auth: {
            strategies: ['token'],
            scope: ['build', 'user', '!guest']
        },
        plugins: {
            'hapi-swagger': {
                security: [{ token: [] }]
            }
        },
        handler: (request, reply) => {
            const { namespace, name } = request.params;
            const { credentials } = request.auth;
            const { commandFactory, commandTagFactory } = request.server.app;
            const { canRemove } = request.server.plugins.commands;
            const storeUrl = request.server.app.ecosystem.store;
            const authToken = request.headers.authorization;

            return Promise.all([
                commandFactory.list({ params: { namespace, name } }),
                commandTagFactory.list({ params: { namespace, name } })
            ]).then(([commands, tags]) => {
                if (commands.length === 0) {
                    throw boom.notFound(`Command ${namespace}/${name} does not exist`);
                }

                return canRemove(credentials, commands[0], 'admin').then(() => {
                    // eslint-disable-next-line max-len
                    const commandPromises = commands.map(command => removeCommand(command, storeUrl, authToken));
                    const tagPromises = tags.map(tag => tag.remove());

                    return Promise.all(commandPromises.concat(tagPromises));
                })
                    .then(() => reply().code(204));
            })
                .catch(err => reply(boom.boomify(err)));
        },
        validate: {
            params: {
                namespace: joi.reach(baseSchema, 'namespace'),
                name: joi.reach(baseSchema, 'name')
            }
        }
    }
});
module.exports = () => ({
    method: 'GET',
    path: '/pipelines/{id}/events',
    config: {
        description: 'Get pipeline type events for this pipeline',
        notes: 'Returns pipeline events for the given pipeline',
        tags: ['api', 'pipelines', 'events'],
        auth: {
            strategies: ['token'],
            scope: ['user', 'build', 'pipeline']
        },
        plugins: {
            'hapi-swagger': {
                security: [{ token: [] }]
            }
        },
        handler: (request, reply) => {
            const factory = request.server.app.pipelineFactory;

            return factory.get(request.params.id)
                .then((pipeline) => {
                    if (!pipeline) {
                        throw boom.notFound('Pipeline does not exist');
                    }

                    const eventType = request.query.type || 'pipeline';
                    const config = { params: { type: eventType } };

                    if (request.query.page || request.query.count) {
                        config.paginate = {
                            page: request.query.page,
                            count: request.query.count
                        };
                    }

                    if (request.query.prNum) {
                        config.params.type = 'pr';
                        config.params.prNum = request.query.prNum;
                    }

                    return pipeline.getEvents(config);
                })
                .then(events => reply(events.map(e => e.toJson())))
                .catch(err => reply(boom.boomify(err)));
        },
        response: {
            schema: listSchema
        },
        validate: {
            query: schema.api.pagination.concat(joi.object({
                type: joi.string(),
                prNum: joi.reach(schema.models.event.base, 'prNum')
            }))
        }
    }
});
Exemple #3
0
  getDefault(key) {
    const schemaKey = Array.isArray(key) ? key.join('.') : key;

    const subSchema = Joi.reach(this.getSchema(), schemaKey);
    if (!subSchema) {
      throw new Error(`Unknown config key: ${key}.`);
    }

    return clone(_.get(Joi.describe(subSchema), 'flags.default'));
  }
    validateField(field, value) {
        let subSchema = Joi.reach(this.schema, field)

        try{
            Joi.assert(value, subSchema)
            if(this._errors[field]) delete this._errors[field]
        } catch(error) {
            if(!this._errors[field]) this._errors[field] = {}

            for(let detail of error.details) {
                this._errors[field] = {
                    message: detail.message
                }
            }
        }
    }
Exemple #5
0
module.exports = () => ({
    method: 'DELETE',
    path: '/templates/{name}',
    config: {
        description: 'Delete a template',
        notes: 'Returns null if successful',
        tags: ['api', 'templates'],
        auth: {
            strategies: ['token'],
            scope: ['build', 'user', '!guest']
        },
        plugins: {
            'hapi-swagger': {
                security: [{ token: [] }]
            }
        },
        handler: (request, reply) => {
            const { name } = request.params;
            const { credentials } = request.auth;
            const { templateFactory, templateTagFactory } = request.server.app;
            const { canRemove } = request.server.plugins.templates;

            return Promise.all([
                templateFactory.list({ params: { name } }),
                templateTagFactory.list({ params: { name } })
            ]).then(([templates, tags]) => {
                if (templates.length === 0) {
                    throw boom.notFound(`Template ${name} does not exist`);
                }

                return canRemove(credentials, templates[0], 'admin').then(() => {
                    const templatePromises = templates.map(template => template.remove());
                    const tagPromises = tags.map(tag => tag.remove());

                    return Promise.all(templatePromises.concat(tagPromises));
                })
                    .then(() => reply().code(204));
            })
                .catch(err => reply(boom.boomify(err)));
        },
        validate: {
            params: {
                name: joi.reach(baseSchema, 'name')
            }
        }
    }
});
Exemple #6
0
Fichier : get.js Projet : catto/api
'use strict';

const boom = require('boom');
const joi = require('joi');
const schema = require('screwdriver-data-schema');
const getSchema = schema.models.event.get;
const idSchema = joi.reach(schema.models.event.base, 'id');

module.exports = () => ({
    method: 'GET',
    path: '/events/{id}',
    config: {
        description: 'Get a single event',
        notes: 'Returns a event record',
        tags: ['api', 'events'],
        handler: (request, reply) => {
            const factory = request.server.app.eventFactory;

            return factory.get(request.params.id)
                .then((model) => {
                    if (!model) {
                        throw boom.notFound('Event does not exist');
                    }

                    return reply(model.toJson());
                })
                .catch(err => reply(boom.wrap(err)));
        },
        response: {
            schema: getSchema
        },
Exemple #7
0
'use strict';

const boom = require('boom');
const joi = require('joi');
const schema = require('screwdriver-data-schema');
const idSchema = joi.reach(schema.models.banner.base, 'id');

module.exports = () => ({
    method: 'PUT',
    path: '/banners/{id}',
    config: {
        description: 'Update a banner',
        notes: 'Update a banner',
        tags: ['api', 'banners'],
        auth: {
            strategies: ['token'],
            scope: ['user', '!guest']
        },
        plugins: {
            'hapi-swagger': {
                security: [{ token: [] }]
            }
        },
        handler: (request, reply) => {
            const { bannerFactory } = request.server.app;
            const id = request.params.id; // id of banner to update
            const username = request.auth.credentials.username;
            const scmContext = request.auth.credentials.scmContext;

            // lookup whether user is admin
            const adminDetails = request.server.plugins.banners
Exemple #8
0
'use strict';

const boom = require('boom');
const joi = require('joi');
const schema = require('screwdriver-data-schema');
const idSchema = joi.reach(schema.models.job.base, 'id');

module.exports = () => ({
    method: 'PUT',
    path: '/jobs/{id}',
    config: {
        description: 'Update a job',
        notes: 'Update a specific job',
        tags: ['api', 'jobs'],
        auth: {
            strategies: ['token'],
            scope: ['user', '!guest']
        },
        plugins: {
            'hapi-swagger': {
                security: [{ token: [] }]
            }
        },
        handler: (request, reply) => {
            const { jobFactory, pipelineFactory, userFactory } = request.server.app;
            const id = request.params.id;
            const username = request.auth.credentials.username;
            const scmContext = request.auth.credentials.scmContext;

            return jobFactory.get(id)
                .then((job) => {
Exemple #9
0
'use strict';

const boom = require('boom');
const joi = require('joi');
const schema = require('screwdriver-data-schema');
const winston = require('winston');
const getSchema = schema.models.collection.get;
const idSchema = joi.reach(schema.models.collection.base, 'id');

/**
 * Helper function to get PR info of pipeline
 *
 * @param   {Pipeline} pipeline  Pipeline model to get PR info for
 * @returns {Object}
 */
function getPipelinePRInfo(pipeline) {
    const prs = {
        open: 0,
        failing: 0
    };

    // Get all the PR jobs
    return pipeline.getJobs({ type: 'pr' })
        .then((prJobs) => {
            if (!prJobs) {
                return prs;
            }

            // Return array of prJobs' builds
            return Promise.all(prJobs.map(job =>
                job.getBuilds()
Exemple #10
0
exports.register = (server, options, next) => {
    server.route({
        method: 'GET',
        path: '/isAdmin',
        config: {
            description: 'Check if a user is admin of a pipeline, event, or job',
            notes: 'Returns true or false',
            tags: ['api'],
            auth: {
                strategies: ['token'],
                scope: ['user']
            },
            plugins: {
                'hapi-swagger': {
                    security: [{ token: [] }]
                }
            },
            handler: (request, reply) =>
                Promise.resolve().then(() => {
                    const { pipelineId, eventId, jobId } = request.query;

                    if (eventId) {
                        const eventFactory = request.server.app.eventFactory;

                        return eventFactory.get(eventId).then(e => e.pipelineId);
                    }
                    if (jobId) {
                        const jobFactory = request.server.app.jobFactory;

                        return jobFactory.get(jobId).then(j => j.pipelineId);
                    }

                    return pipelineId;
                }).then((pid) => {
                    const pipelineFactory = request.server.app.pipelineFactory;
                    const userFactory = request.server.app.userFactory;
                    const username = request.auth.credentials.username;
                    const scmContext = request.auth.credentials.scmContext;

                    return Promise.all([
                        pipelineFactory.get(pid),
                        userFactory.get({ username, scmContext })
                    ]).then(([pipeline, user]) => {
                        if (!pipeline) {
                            throw boom.notFound(`Pipeline ${pid} does not exist`);
                        }

                        // ask the user for permissions on this repo
                        return user.getPermissions(pipeline.scmUri)
                            .then(permissions => reply(permissions.admin));
                    });
                }).catch(err => reply(boom.boomify(err))),
            validate: {
                query: joi.object().keys({
                    pipelineId: joi.reach(schema.models.pipeline.base, 'id'),
                    eventId: joi.reach(schema.models.event.base, 'id'),
                    jobId: joi.reach(schema.models.job.base, 'id')
                }).max(1).min(1)
            }
        }
    });

    next();
};
'use strict';

const Joi = require('joi');
const Build = require('../models/build');

const SCHEMA_PARAMS = Joi.object().keys({
    id: Joi.reach(Build.base, 'id'),
    name: Joi.reach(Build.getStep, 'name')
}).label('URL Parameters');

const SCHEMA_QUERY = Joi.object().keys({
    from: Joi.number().integer()
        .min(0)
        .default(0)
        .description('Starting line Number'),
    pages: Joi.number().integer()
        .min(1)
        .default(10)
        .description('Max pages sent per request'),
    sort: Joi
        .string().lowercase()
        .valid(['ascending', 'descending'])
        .default('ascending')
        .description('Sorting option for lines')
}).label('Query Parameters');

const SCHEMA_LOGLINE = Joi.object().keys({
    n: Joi
        .number().integer()
        .description('Numbered line number since the start of the step')
        .example(15),
Exemple #12
0
'use strict';

const boom = require('boom');
const joi = require('joi');
const schema = require('screwdriver-data-schema');
const idSchema = joi.reach(schema.models.token.base, 'id');

module.exports = () => ({
    method: 'PUT',
    path: '/tokens/{id}/refresh',
    config: {
        description: 'Refresh a token',
        notes: 'Update the value of a token while preserving its other metadata',
        tags: ['api', 'tokens'],
        auth: {
            strategies: ['token'],
            scope: ['user', '!guest']
        },
        plugins: {
            'hapi-swagger': {
                security: [{ token: [] }]
            }
        },
        handler: (request, reply) => {
            const tokenFactory = request.server.app.tokenFactory;
            const credentials = request.auth.credentials;
            const canAccess = request.server.plugins.tokens.canAccess;

            return tokenFactory.get(request.params.id)
                .then((token) => {
                    if (!token) {
Exemple #13
0
    stateChangeMessage: Joi
        .string()
        .max(512)
        .description('Reason why disabling or enabling job')
        .example('Testing out new feature change in beta only'),

    archived: Joi
        .boolean()
        .description('Flag if the job is archived')
        .example(true)
        .default(false)
};

const EXTENDED_MODEL = {
    title: Joi.reach(SCM_PR_SCHEMA, 'title'),
    createTime: Joi.reach(SCM_PR_SCHEMA, 'createTime'),
    username: Joi.reach(SCM_PR_SCHEMA, 'username'),
    userProfile: Joi.reach(SCM_PR_SCHEMA, 'userProfile'),
    url: Joi.reach(SCM_PR_SCHEMA, 'url'),
    ...MODEL
};

module.exports = {
    /**
     * All the available properties of Job
     *
     * @property base
     * @type {Joi}
     */
    base: Joi.object(MODEL).label('Job'),
'use strict';

const Joi = require('joi');
const mutate = require('../lib/mutate');
const Command = require('../config/command');
const scmContext = Joi.reach(require('./pipeline').base, 'scmContext');
const scmOrganization = Joi
    .string().max(100)
    .description('SCM organization name')
    .example('screwdriver-cd');

const MODEL = {
    id: Joi
        .number().integer().positive()
        .description('Identifier of this Job')
        .example(123345),

    name: Joi
        .string().regex(/^[\w-]+$/)
        .max(50)
        .description('Name of the build cluster')
        .example('iOS'),

    description: Joi
        .string().max(100)
        .description('Description of the build cluster')
        .example('Build cluster for iOS team'),

    scmContext,

    scmOrganizations: Joi.array().items(scmOrganization),
Exemple #15
0
'use strict';

const boom = require('boom');
const joi = require('joi');
const schema = require('screwdriver-data-schema');
const getSchema = schema.models.buildCluster.get;
const nameSchema = joi.reach(schema.models.buildCluster.base, 'name');

module.exports = () => ({
    method: 'GET',
    path: '/buildclusters/{name}',
    config: {
        description: 'Get a single build cluster',
        notes: 'Returns a build cluster record',
        tags: ['api', 'buildclusters'],
        auth: {
            strategies: ['token'],
            scope: ['user', 'build']
        },
        plugins: {
            'hapi-swagger': {
                security: [{ token: [] }]
            }
        },
        handler: (request, reply) => {
            const name = request.params.name;
            const factory = request.server.app.buildClusterFactory;
            const config = {
                params: {
                    name
                }
module.exports = config => ({
    method: 'GET',
    path: '/pipelines/{id}/{jobName}/badge',
    config: {
        description: 'Get a badge for a job',
        notes: 'Redirects to the badge service',
        tags: ['api', 'job', 'badge'],
        handler: (request, reply) => {
            const jobFactory = request.server.app.jobFactory;
            const pipelineFactory = request.server.app.pipelineFactory;
            const { id, jobName } = request.params;
            const badgeService = request.server.app.ecosystem.badges;
            const encodeBadgeSubject = request.server.plugins.pipelines.encodeBadgeSubject;
            const { statusColor } = config;
            const badgeConfig = {
                badgeService,
                statusColor,
                encodeBadgeSubject
            };

            return Promise.all([
                jobFactory.get({
                    pipelineId: id,
                    name: jobName
                }),
                pipelineFactory.get(id)
            ]).then(([job, pipeline]) => {
                if (!job) {
                    return reply.redirect(getUrl(badgeConfig));
                }

                if (job.state === 'DISABLED') {
                    return reply.redirect(getUrl(Object.assign(
                        badgeConfig,
                        {
                            builds: [{
                                status: 'DISABLED'
                            }],
                            subject: `${pipeline.name}:${jobName}`
                        })));
                }

                const listConfig = {
                    paginate: {
                        page: 1,
                        count: 1
                    }
                };

                return job.getBuilds(listConfig)
                    .then(builds => reply.redirect(getUrl(Object.assign(
                        badgeConfig,
                        {
                            builds,
                            subject: `${pipeline.name}:${jobName}`
                        }))));
            }).catch(() => reply.redirect(getUrl(badgeConfig)));
        },
        validate: {
            params: {
                id: idSchema,
                jobName: joi.reach(schema.models.job.base, 'name')
            }
        }
    }
});
Exemple #17
0
    scmContext: Joi
        .string().max(128)
        .required()
        .description('The SCM in which the repository exists')
        .example('github:github.com'),

    sha: Joi.string().hex()
        .when('action', { is: ['release', 'tag'], then: Joi.allow('').optional() })
        .when('type', { is: 'ping', then: Joi.allow('').optional(), otherwise: Joi.required() })
        .label('Commit SHA')
        .example('ccc49349d3cffbd12ea9e3d41521480b4aa5de5f'),

    type: Joi.string()
        .valid(['pr', 'repo', 'ping'])
        .required()
        .label('Type of the event'),

    username: Joi.reach(SCHEMA_USER, 'username')
}).label('SCM Hook');

module.exports = {
    command: SCHEMA_COMMAND,
    commit: SCHEMA_COMMIT,
    repo: SCHEMA_REPO,
    repoName: REPO_NAME,
    user: SCHEMA_USER,
    hook: SCHEMA_HOOK,
    pr: SCHEMA_PR
};
Exemple #18
0
module.exports = () => ({
    method: 'PUT',
    path: '/templates/{templateName}/tags/{tagName}',
    config: {
        description: 'Add or update a template tag',
        notes: 'Add or update a specific template',
        tags: ['api', 'templates'],
        auth: {
            strategies: ['token', 'session'],
            scope: ['build']
        },
        plugins: {
            'hapi-swagger': {
                security: [{ token: [] }]
            }
        },
        handler: (request, reply) => {
            const pipelineFactory = request.server.app.pipelineFactory;
            const templateFactory = request.server.app.templateFactory;
            const templateTagFactory = request.server.app.templateTagFactory;
            const pipelineId = request.auth.credentials.pipelineId;
            const name = request.params.templateName;
            const tag = request.params.tagName;
            const version = request.payload.version;

            return Promise.all([
                pipelineFactory.get(pipelineId),
                templateFactory.get({ name, version }),
                templateTagFactory.get({ name, tag })
            ]).then(([pipeline, template, templateTag]) => {
                // If template doesn't exist, throw error
                if (!template) {
                    throw boom.notFound(`Template ${name}@${version} not found`);
                }

                // If template exists, but this build's pipelineId is not the same as template's pipelineId
                // Then this build does not have permission to tag the template
                if (pipeline.id !== template.pipelineId) {
                    throw boom.unauthorized('Not allowed to tag this template');
                }

                // If template tag exists, then the only thing it can update is the version
                if (templateTag) {
                    templateTag.version = version;

                    return templateTag.update().then(newTag => reply(newTag.toJson()).code(200));
                }

                // If template exists, then create the tag
                return templateTagFactory.create({ name, tag, version })
                    .then((newTag) => {
                        const location = urlLib.format({
                            host: request.headers.host,
                            port: request.headers.port,
                            protocol: request.server.info.protocol,
                            pathname: `${request.path}/${newTag.id}`
                        });

                        return reply(newTag.toJson()).header('Location', location).code(201);
                    });
            }).catch(err => reply(boom.wrap(err)));
        },
        validate: {
            params: {
                templateName: joi.reach(baseSchema, 'name'),
                tagName: joi.reach(baseSchema, 'tag')
            },
            payload: {
                version: joi.reach(baseSchema, 'version')
            }
        }
    }
});
'use strict';

const Joi = require('joi');
const mutate = require('../lib/mutate');
const Template = require('../config/template');
const pipelineId = Joi.reach(require('./pipeline').base, 'id');

const MODEL = {
    id: Joi
        .number().integer().positive()
        .description('Identifier of this template')
        .example(123345),
    labels: Joi
        .array()
        .items(Joi.string())
        .description('Labels for template')
        .example(['stable', 'latest', 'beta']),
    config: Template.config,
    name: Joi
        .string()
        .max(64)
        .description('Template name')
        .example('nodejs/lib'),
    version: Template.version,
    description: Template.description,
    maintainer: Template.maintainer,
    pipelineId,
    namespace: Template.namespace,
    images: Template.images,
    createTime: Joi
        .string()
Exemple #20
0
'use strict';

const boom = require('boom');
const joi = require('joi');
const schema = require('screwdriver-data-schema');
const getSchema = schema.models.template.get;
const nameSchema = joi.reach(schema.models.template.base, 'name');
const versionSchema = joi.reach(schema.models.template.base, 'version');
const tagSchema = joi.reach(schema.models.templateTag.base, 'tag');

module.exports = () => ({
    method: 'GET',
    path: '/templates/{name}/{versionOrTag}',
    config: {
        description: 'Get a single template given template name and version or tag',
        notes: 'Returns a template record',
        tags: ['api', 'templates'],
        auth: {
            strategies: ['token'],
            scope: ['user', 'build']
        },
        plugins: {
            'hapi-swagger': {
                security: [{ token: [] }]
            }
        },
        handler: (request, reply) => {
            const templateFactory = request.server.app.templateFactory;
            const { name, versionOrTag } = request.params;

            return templateFactory.getTemplate(`${name}@${versionOrTag}`)
Exemple #21
0
'use strict';

const joi = require('joi');
const schema = require('screwdriver-data-schema');
const workflowParser = require('screwdriver-workflow-parser');
const tinytim = require('tinytim');
const idSchema = joi.reach(schema.models.pipeline.base, 'id');

/**
 * Generate Badge URL
 * @method getUrl
 * @param  {String} badgeService            Badge service url
 * @param  {Object} statusColor             Mapping for status and color
 * @param  {Function} encodeBadgeSubject    Function to encode subject
 * @param  {Array}  [buildsStatus=[]]       An array of builds
 * @param  {String} [subject='job']         Subject of the badge
 * @return {String}
 */
function getUrl({
    badgeService,
    statusColor,
    encodeBadgeSubject,
    buildsStatus = [],
    subject = 'pipeline' }) {
    const counts = {};
    const parts = [];
    let worst = 'lightgrey';

    const levels = Object.keys(statusColor);

    buildsStatus.forEach((status) => {
'use strict';

const Annotations = require('../config/annotations');
const Job = require('../config/job');
const Joi = require('joi');
const models = require('../models');
const buildId = Joi.reach(models.build.base, 'id').required();
const eventId = Joi.reach(models.event.base, 'id');
const jobId = Joi.reach(models.job.base, 'id');
const jobName = Joi.reach(models.job.base, 'name');

const SCHEMA_PIPELINE = Joi.object().keys({
    id: Joi.reach(models.pipeline.base, 'id').required(),
    scmContext: Joi.reach(models.pipeline.base, 'scmContext').required()
}).unknown();

const SCHEMA_START = Joi.object().keys({
    build: Joi.object(),
    jobId,
    jobName,
    annotations: Annotations.annotations,
    blockedBy: Joi.array().items(jobId),
    freezeWindows: Job.freezeWindows,
    buildId,
    eventId,
    tokenGen: Joi.func(),
    pipeline: SCHEMA_PIPELINE,
    buildClusterName: Joi.reach(models.buildCluster.base, 'name'),
    container: Joi.reach(models.build.base, 'container').required(),
    apiUri: Joi.string().uri().required()
        .label('API URI'),