"""Database model for application.""" from flask_sqlalchemy import SQLAlchemy import requests import yaml db = SQLAlchemy() host_classes = db.Table( 'host_classes', db.Column('host_id', db.ForeignKey('host.id')), db.Column('class_id', db.ForeignKey('puppet_class.id'))) # class HostClasses(db.Model): # __tablename__ = 'host_classes' # id = db.Column(db.Integer, primary_key=True) # host_id = db.Column(db.Integer, db.ForeignKey('host.id'), nullable=False) # class_id = db.Column(db.Integer, db.ForeignKey('puppet_class.id'), nullable=False) class Host(db.Model): """ Single computer. A computer has a name (machine.example.com.), an environment (production) and a list of puppet classes. (TODO and direct values?) """ __tablename__ = 'host' id = db.Column(db.Integer, primary_key=True) fqdn = db.Column(db.Text, nullable=False) environment = db.Column(db.Text) # classes = db.relationship('HostClasses', backref='host', lazy='dynamic') classes = db.relationship( 'PuppetClass', back_populates='hosts', secondary=host_classes) def serialize(self): return {column.name: self.__getattribute__(column.name) for column in self.__table__.columns} class PuppetEnvironment(db.Model): """ A puppet environment. An enviromnet is a collection of modules, but here we only keep the files of the modules, in PuppetFile. """ __tablename__ = 'puppet_environment' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.Text, nullable=False) class PuppetFile(db.Model): """ Puppet source code file. Keeps track of known puppet files. Each file contains 0 to many puppet classes. Each file is uniquely identified by the pair (path, environment). """ __tablename__ = 'puppet_file' id = db.Column(db.Integer, primary_key=True) # Where we found the file # TODO normalize this to path = db.Column(db.Text, nullable=False) environment = db.Column(db.Integer, db.ForeignKey(f'{PuppetEnvironment.__tablename__}.id')) # Checksum of the content, should be usable as a key in # PuppetFileContent # TODO flask weak keys? checksum = db.Column(db.Text) # When we last read data into json last_parse = db.Column(db.Float) # classes = db.relationship('PuppetClass', back_populates='comes_from') classes = db.relationship('PuppetClass', backref='comes_from') class PuppetFileContent(db.Model): """ (Parsed) contents of puppet source files. Separate from PuppetFile since many environments can share files, and I don't want to store reduntand data. """ __tablename__ = 'puppet_file_content' id = db.Column(db.Integer, primary_key=True) # Checksum of the original file checksum = db.Column(db.Text, nullable=False) # Output of 'puppet parser dump --format json ' json = db.Column(db.Text, nullable=False) class PuppetClass(db.Model): """ A puppet class. The class itself only keeps track of its name here, and mostyl ensures that only existing classes can be added to a given node/host. """ __tablename__ = 'puppet_class' id = db.Column(db.Integer, primary_key=True) class_name = db.Column(db.Text, nullable=False) # comes_from = db.relationship('PuppetFile', back_populates='classes') comes_from_id = db.Column(db.Integer, db.ForeignKey(f'{PuppetFile.__tablename__}.id')) hosts = db.relationship( 'Host', back_populates='classes', secondary=host_classes)