Skip to content
Snippets Groups Projects
inau.py 69 KiB
Newer Older
#file_fields = { 'filename': fields.String(), 'hash': fields.String() }
#class FileHandler(Resource):
#    @marshal_with(file_fields)
#    def get(self, facilityname, hostname, filename):
#        host = Hosts.query.join('facility').\
#                filter(Facilities.name == facilityname,
#                        Hosts.name == hostname).\
#                first_or_404()
#        LatestInstallations = db.session.query(Installations)\
#                .with_entities(Repositories.id, Installations.host_id,\
#                    func.max(Installations.id).label('installation_id'))\
#                .select_from(Installations)\
#                .join(Builds).join(Repositories)\
#                .group_by(Repositories.id, Installations.host_id)\
#                .subquery()
#        artifact = Builds.query.\
#                join('installations').\
#                join('artifacts').\
#                join(LatestInstallations, Installations.id == LatestInstallations.c.installation_id).\
#                with_entities(Artifacts).\
#                filter(Artifacts.filename == filename, Installations.host == host).\
#                first_or_404()
#        return { 'filename': artifact.filename, 'hash': artifact.hash }
Alessio Igor Bogani's avatar
Alessio Igor Bogani committed

mode_parser = reqparse.RequestParser()
mode_parser.add_argument('mode', type=str, default='status', required=False,
        choices=['status', 'diff', 'history'], location='args')

cs_installations_fields = { 'facility': fields.String(),
        'host': fields.String(), 'repository': fields.String(),
        'tag': fields.String(), 'date': fields.DateTime(),
        'author': fields.String() }
class CSInstallationsHandler(Resource):
    @marshal_with(cs_installations_fields)
    def get(self):
        args = mode_parser.parse_args(strict=True)
        LatestInstallations = db.session.query(Installations)\
                .with_entities(Repositories.id, Installations.host_id,\
                    func.max(Installations.id).label('installation_id'))\
                .select_from(Installations)\
                .join(Builds).join(Repositories)\
                .group_by(Repositories.id, Installations.host_id)\
                .subquery()
Alessio Igor Bogani's avatar
Alessio Igor Bogani committed
        if args['mode'] == 'status':
            installations = Installations.query.options(
                    joinedload('user', innerjoin=True),\
                    joinedload('build', innerjoin=True).\
                    joinedload('repository', innerjoin=True),
                    joinedload('host', innerjoin=True).\
                    joinedload('facility', innerjoin=True)).\
                    join(LatestInstallations, Installations.id == LatestInstallations.c.installation_id).\
                    order_by(Installations.date.desc()).all()
        elif args['mode'] == 'diff':
            installations = Installations.query.options(
                    joinedload('user', innerjoin=True),\
                    joinedload('build', innerjoin=True).\
                    joinedload('repository', innerjoin=True),
                    joinedload('host', innerjoin=True).\
                    joinedload('facility', innerjoin=True)).\
                    join(LatestInstallations, Installations.id == LatestInstallations.c.installation_id).\
                    filter(Installations.type != int(InstallationType.GLOBAL)).\
                    order_by(Installations.date.desc()).all()
        else: # history
            installations = Installations.query.options(
                    joinedload('user', innerjoin=True),\
                    joinedload('build', innerjoin=True).\
                    joinedload('repository', innerjoin=True),
                    joinedload('host', innerjoin=True).\
                    joinedload('facility', innerjoin=True)).\
                order_by(Installations.date.desc()).all()
        retval = []
        for installation in installations:
            retval.append({ 'facility': installation.host.facility.name, 
                'host': installation.host.name,
                'repository': installation.build.repository.name,
                'tag': installation.build.tag, 'date': installation.date,
                'author': installation.user.name })
        return retval, 200 if len(retval) else 204
    @marshal_with(cs_installations_fields)
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('repository', required=True, trim=True, nullable=False,
                type=non_empty_string, help='{error_msg} (e.g. repository=fake)')
        parser.add_argument('tag', required=True, trim=True, nullable=False,
                type=non_empty_string, help='{error_msg} (e.g. tag=0.0.4)')
        args = parser.parse_args(strict=True)
        username = authenticate(AuthenticationType.USER, request)
        destinations = {}
        for repository in Repositories.query.\
                filter(Repositories.name == args['repository']).\
                filter(Repositories.enabled == 1).\
Alessio Igor Bogani's avatar
Alessio Igor Bogani committed
                all():
            for server in repository.platform.servers:
                for host in server.hosts:
                    try:
                        destinations[host.server].add(host)
                    except KeyError:
                        destinations[host.server] = {host}
        return install(username, args['repository'], args['tag'],
                destinations, InstallationType.GLOBAL)

facility_installations_fields = { 'host': fields.String(),
        'repository': fields.String(), 'tag': fields.String(),
        'date': fields.DateTime(), 'author': fields.String() }
class FacilityInstallationsHandler(Resource):
    @marshal_with(facility_installations_fields)
    def get(self, facilityname):
        facility = Facilities.query.\
                filter(Facilities.name == facilityname).\
                first_or_404()
        args = mode_parser.parse_args(strict=True)
        LatestInstallations = db.session.query(Installations)\
                .with_entities(Repositories.id, Installations.host_id,\
                    func.max(Installations.id).label('installation_id'))\
                .select_from(Installations)\
                .join(Builds).join(Repositories)\
                .group_by(Repositories.id, Installations.host_id)\
                .subquery()
Alessio Igor Bogani's avatar
Alessio Igor Bogani committed
        if args['mode'] == 'status':
            installations = Installations.query.options(
                    joinedload('user', innerjoin=True),\
                    joinedload('build', innerjoin=True).\
                    joinedload('repository', innerjoin=True),
                    joinedload('host', innerjoin=True)).\
                    join('host').\
                    join(LatestInstallations, Installations.id == LatestInstallations.c.installation_id).\
                    filter(Hosts.facility == facility).\
                    order_by(Installations.date.desc()).all()
        elif args['mode'] == 'diff':
            installations = Installations.query.options(
                    joinedload('user', innerjoin=True),\
                    joinedload('build', innerjoin=True).\
                    joinedload('repository', innerjoin=True),
                    joinedload('host', innerjoin=True)).\
                    join('host').\
                    join(LatestInstallations, Installations.id == LatestInstallations.c.installation_id).\
                    filter(Hosts.facility == facility,
                            Installations.type == int(InstallationType.HOST)).\
                    order_by(Installations.date.desc()).all()
        else: # history
            installations = Installations.query.options(
                    joinedload('user', innerjoin=True),\
                    joinedload('build', innerjoin=True).\
                    joinedload('repository', innerjoin=True),
                    joinedload('host', innerjoin=True)).\
                    join('host').\
                    filter(Hosts.facility == facility).\
                    order_by(Installations.date.desc()).all()
        retval = []
        for installation in installations:
            retval.append({ 'host': installation.host.name,
                'repository': installation.build.repository.name,
                'tag': installation.build.tag, 'date': installation.date,
                'author': installation.user.name })
        return retval, 200 if len(retval) else 204
    @marshal_with(facility_installations_fields)
    def post(self, facilityname):
        facility = Facilities.query.filter(Facilities.name == facilityname) \
                .first_or_404()
        parser = reqparse.RequestParser()
        parser.add_argument('repository', required=True, trim=True, nullable=False,
                type=non_empty_string, help='{error_msg} (e.g. repository=fake)')
        parser.add_argument('tag', required=True, trim=True, nullable=False,
                type=non_empty_string, help='{error_msg} (e.g. tag=0.0.4)')
        args = parser.parse_args(strict=True)
        username = authenticate(AuthenticationType.USER, request)
        destinations = {}
        for repository in Repositories.query.\
                filter(Repositories.name == args['repository']).\
                filter(Repositories.enabled == 1).\
Alessio Igor Bogani's avatar
Alessio Igor Bogani committed
                all():
                    for server in repository.platform.servers:
                        for host in server.hosts:
                            if host.facility_id != facility.id:
                                continue
                            try:
                                destinations[host.server].add(host)
                            except KeyError:
                                destinations[host.server] = {host}
        return install(username, args['repository'], args['tag'], 
                destinations, InstallationType.FACILITY)

host_installations_fields = { 'repository': fields.String(),
        'tag': fields.String(), 'date': fields.DateTime(),
        'author': fields.String() }
class HostInstallationsHandler(Resource):
    @marshal_with(host_installations_fields)
    def get(self, facilityname, hostname):
        host = Hosts.query.join('facility').\
                filter(Facilities.name == facilityname,
                        Hosts.name == hostname).\
                first_or_404()
        args = mode_parser.parse_args(strict=True)
        LatestInstallations = db.session.query(Installations)\
                .with_entities(Repositories.id, Installations.host_id,\
                    func.max(Installations.id).label('installation_id'))\
                .select_from(Installations)\
                .join(Builds).join(Repositories)\
                .group_by(Repositories.id, Installations.host_id)\
                .subquery()
Alessio Igor Bogani's avatar
Alessio Igor Bogani committed
        if args['mode'] == 'status':
            installations = Installations.query.options(
                    joinedload('user', innerjoin=True),\
                    joinedload('build', innerjoin=True).\
                    joinedload('repository', innerjoin=True),
                    joinedload('host', innerjoin=True)).\
                    join(LatestInstallations, Installations.id == LatestInstallations.c.installation_id).\
                    filter(Installations.host == host).\
                    order_by(Installations.date.desc()).all()
        elif args['mode'] == 'diff':
            installations = Installations.query.options(
                    joinedload('user', innerjoin=True),\
                    joinedload('build', innerjoin=True).\
                    joinedload('repository', innerjoin=True),
                    joinedload('host', innerjoin=True)).\
                    join(LatestInstallations, Installations.id == LatestInstallations.c.installation_id).\
                    filter(Installations.host == host,
                            Installations.type == int(InstallationType.HOST)).\
                    order_by(Installations.date.desc()).all()
        else: # history
            installations = Installations.query.options(
                    joinedload('user', innerjoin=True),\
                    joinedload('build', innerjoin=True).\
                    joinedload('repository', innerjoin=True),
                    joinedload('host', innerjoin=True)).\
                    filter(Installations.host == host).\
                    order_by(Installations.date.desc()).all()
        retval = []
        for installation in installations:
            retval.append({ 'repository': installation.build.repository.name,
                'tag': installation.build.tag, 'date': installation.date,
                'author': installation.user.name })
        return retval, 200 if len(retval) else 204
    @marshal_with(host_installations_fields)
    def post(self, facilityname, hostname):
        host = Hosts.query.options(joinedload('facility', innerjoin=True)) \
                .filter(Facilities.name == facilityname, Hosts.name == hostname) \
                .first_or_404()
        parser = reqparse.RequestParser()
        parser.add_argument('repository', required=True, trim=True, nullable=False,
                type=non_empty_string, help='{error_msg} (e.g. repository=fake)')
        parser.add_argument('tag', required=True, trim=True, nullable=False,
                type=non_empty_string, help='{error_msg} (e.g. tag=0.0.4)')
        args = parser.parse_args(strict=True)
        username = authenticate(AuthenticationType.USER, request)
        destinations = {}
        destinations[host.server] = {host}
        return install(username, args['repository'], args['tag'], 
                destinations, InstallationType.HOST)
        return {}

def retrieveAnnotatedTags(gitrepo):
    atags = set()
    for atag in gitrepo.tags:
        if atag.tag != None:
            atags.add(atag)
    return atags

def updateRepo(repo):
    gitrepo = None
    atagsBefore = set()
    repoPath = app.config['GIT_TREES_DIR'] + repo.name
    if os.path.isdir(repoPath):
        gitrepo = git.Repo(repoPath)
Alessio Igor Bogani's avatar
Alessio Igor Bogani committed
        gitrepo.git.clean("-fdx")
        gitrepo.git.reset('--hard')
        gitrepo.git.checkout("master")
Alessio Igor Bogani's avatar
Alessio Igor Bogani committed
        atagsBefore = retrieveAnnotatedTags(gitrepo)
        gitrepo.remotes.origin.fetch()
        gitrepo.submodule_update(recursive=True, init=False, force_reset=True)
Alessio Igor Bogani's avatar
Alessio Igor Bogani committed
    else:
        gitrepo = git.Repo.clone_from(repo.provider.url + repo.name, to_path=repoPath)
        gitrepo.submodule_update(recursive=True, init=True, force_reset=False)
Alessio Igor Bogani's avatar
Alessio Igor Bogani committed
    atagsAfter = set()
    atagsAfter = retrieveAnnotatedTags(gitrepo)
    return gitrepo, atagsAfter - atagsBefore


if __name__ == '__main__':
    # Configure Flask
    app.config['SQLALCHEMY_DATABASE_URI'] = args.db
    app.config['MAIL_SERVER'] = args.smtpserver
    app.config['MAIL_DOMAIN'] = args.smtpdomain
    app.config['MAIL_DEFAULT_SENDER'] = args.smtpsender + "@" + args.smtpdomain
Alessio Igor Bogani's avatar
Alessio Igor Bogani committed
    app.config['FILES_STORE_DIR'] = args.store
    app.config['GIT_TREES_DIR'] = args.repo
    app.config['LDAP_URL'] = args.ldap
    app.config['BUNDLE_ERRORS'] = True
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    if args.port != "443":
        app.debug = True
Alessio Igor Bogani's avatar
Alessio Igor Bogani committed
        app.config['SQLALCHEMY_ECHO'] = True

    # Configure SQLAclhemy
    db.app = app
    db.init_app(app)

    # Create all DB tables if necessary
    db.create_all()

    # Creates REST endpoints
    v2.add_resource(CSHandler, '/cs', '/cs/')
    v2.add_resource(UsersHandler, '/cs/users', '/cs/users/')
    v2.add_resource(UserHandler, '/cs/users/<string:username>',
            '/cs/users/<string:username>/')
    v2.add_resource(ArchitecturesHandler, '/cs/architectures', '/cs/architectures/')
    v2.add_resource(ArchitectureHandler, '/cs/architectures/<string:archname>',
            '/cs/architectures/<string:archname>/')
    v2.add_resource(DistributionsHandler, '/cs/distributions', '/cs/distributions/')
    v2.add_resource(DistributionHandler, '/cs/distributions/<string:distroid>',
            '/cs/distributions/<string:distroid>/')
    v2.add_resource(PlatformsHandler, '/cs/platforms', '/cs/platforms/')
    v2.add_resource(PlatformHandler, '/cs/platforms/<int:platid>',
            '/cs/platforms/<int:platid>/')
    v2.add_resource(BuildersHandler,'/cs/builders', '/cs/builders/')
    v2.add_resource(BuilderHandler, '/cs/builders/<string:buildername>',
            '/cs/builders/<string:buildername>/')
    v2.add_resource(ServersHandler, '/cs/servers', '/cs/servers/')
    v2.add_resource(ServerHandler, '/cs/servers/<string:servername>',
            '/cs/servers/<string:servername>/')
    v2.add_resource(ProvidersHandler, '/cs/providers', '/cs/providers/')
    v2.add_resource(ProviderHandler, '/cs/servers/<int:providerid>',
            '/cs/providers/<int:providerid>/')
    v2.add_resource(RepositoriesHandler, '/cs/repositories', '/cs/repositories/')
    v2.add_resource(RepositoryHandler, '/cs/repositories/<int:repositoryid>',
            '/cs/repositories/<int:repositoryid>/')
    v2.add_resource(FacilitiesHandler, '/cs/facilities', '/cs/facilities/')
    v2.add_resource(FacilityHandler, '/cs/facilities/<string:facilityname>',
            '/cs/facilities/<string:facilityname>/')
    v2.add_resource(HostsHandler, '/cs/facilities/<string:facilityname>/hosts',
            '/cs/facilities/<string:facilityname>/hosts/')
    v2.add_resource(HostHandler, 
            '/cs/facilities/<string:facilityname>/hosts/<string:hostname>',
            '/cs/facilities/<string:facilityname>/hosts/<string:hostname>/')
#    v2.add_resource(FilesHandler, 
#            '/cs/facilities/<string:facilityname>/hosts/<string:hostname>/files',
#            '/cs/facilities/<string:facilityname>/hosts/<string:hostname>/files/')
#    v2.add_resource(FileHandler,
#            '/cs/facilities/<string:facilityname>/hosts/<string:hostname>/files/<string:filename>',
#            '/cs/facilities/<string:facilityname>/hosts/<string:hostname>/files/<string:filename>/')
Alessio Igor Bogani's avatar
Alessio Igor Bogani committed

    v2.add_resource(CSInstallationsHandler, '/cs/installations',
            '/cs/installations/', '/cs/facilities/installations',
            '/cs/facilities/installations/')
    v2.add_resource(FacilityInstallationsHandler, 
            '/cs/facilities/<string:facilityname>/installations', 
            '/cs/facilities/<string:facilityname>/installations/', 
            '/cs/facilities/<string:facilityname>/hosts/installations',
            '/cs/facilities/<string:facilityname>/hosts/installations/')
    v2.add_resource(HostInstallationsHandler,
            '/cs/facilities/<string:facilityname>/hosts/<string:hostname>/installations',
            '/cs/facilities/<string:facilityname>/hosts/<string:hostname>/installations/')

    if args.port != "443":
        app.run(host='0.0.0.0', port=args.port, threaded=True,
                use_reloader=False, use_debugger=False)
    else:
        app.run(host='0.0.0.0', port=args.port, threaded=True,
                ssl_context=('/etc/ssl/certs/inau_elettra_eu.pem',
                    '/etc/ssl/private/inau_elettra_eu.key'),
                use_reloader=False, use_debugger=False)