Refactor pillar model, add Environment and State models and add some basic API endpoints
This commit is contained in:
parent
b37f78b961
commit
c47794ecda
@ -0,0 +1,62 @@
|
||||
"""pillars are directly assigned to the hosts
|
||||
|
||||
Revision ID: 7eb66922e256
|
||||
Revises: 54537e95fc4d
|
||||
Create Date: 2026-02-08 20:34:16.291415
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '7eb66922e256'
|
||||
down_revision: Union[str, Sequence[str], None] = '54537e95fc4d'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('pillar_tool_pillar_value')
|
||||
op.add_column('pillar_tool_pillar', sa.Column('pillar_name', sa.String(), nullable=False))
|
||||
op.add_column('pillar_tool_pillar', sa.Column('host_id', sa.UUID(), nullable=True))
|
||||
op.add_column('pillar_tool_pillar', sa.Column('type', sa.String(), nullable=False))
|
||||
op.add_column('pillar_tool_pillar', sa.Column('value', sa.String(), nullable=False))
|
||||
op.drop_constraint(op.f('pillar_parent_unique_name_parent'), 'pillar_tool_pillar', type_='unique')
|
||||
op.create_unique_constraint('pillar_unique_pillar_name', 'pillar_tool_pillar', ['pillar_name', 'host_id'])
|
||||
op.drop_constraint(op.f('pillar_tool_pillar_parent_id_fkey'), 'pillar_tool_pillar', type_='foreignkey')
|
||||
op.create_foreign_key(None, 'pillar_tool_pillar', 'pillar_tool_host', ['host_id'], ['id'])
|
||||
op.drop_column('pillar_tool_pillar', 'name')
|
||||
op.drop_column('pillar_tool_pillar', 'parent_id')
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('pillar_tool_pillar', sa.Column('parent_id', sa.UUID(), autoincrement=False, nullable=True))
|
||||
op.add_column('pillar_tool_pillar', sa.Column('name', sa.VARCHAR(), autoincrement=False, nullable=False))
|
||||
op.drop_constraint(None, 'pillar_tool_pillar', type_='foreignkey')
|
||||
op.create_foreign_key(op.f('pillar_tool_pillar_parent_id_fkey'), 'pillar_tool_pillar', 'pillar_tool_pillar', ['parent_id'], ['id'])
|
||||
op.drop_constraint('pillar_unique_pillar_name', 'pillar_tool_pillar', type_='unique')
|
||||
op.create_unique_constraint(op.f('pillar_parent_unique_name_parent'), 'pillar_tool_pillar', ['parent_id', 'name'], postgresql_nulls_not_distinct=False)
|
||||
op.drop_column('pillar_tool_pillar', 'value')
|
||||
op.drop_column('pillar_tool_pillar', 'type')
|
||||
op.drop_column('pillar_tool_pillar', 'host_id')
|
||||
op.drop_column('pillar_tool_pillar', 'pillar_name')
|
||||
op.create_table('pillar_tool_pillar_value',
|
||||
sa.Column('id', sa.UUID(), autoincrement=False, nullable=False),
|
||||
sa.Column('pillar_id', sa.UUID(), autoincrement=False, nullable=False),
|
||||
sa.Column('host_id', sa.UUID(), autoincrement=False, nullable=True),
|
||||
sa.Column('type', sa.VARCHAR(), autoincrement=False, nullable=False),
|
||||
sa.Column('value', sa.VARCHAR(), autoincrement=False, nullable=False),
|
||||
sa.ForeignKeyConstraint(['host_id'], ['pillar_tool_host.id'], name=op.f('pillar_tool_pillar_value_host_id_fkey')),
|
||||
sa.ForeignKeyConstraint(['pillar_id'], ['pillar_tool_pillar.id'], name=op.f('pillar_tool_pillar_value_pillar_id_fkey')),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pillar_tool_pillar_value_pkey')),
|
||||
sa.UniqueConstraint('pillar_id', 'host_id', name=op.f('pillar_value_unique_pillar_value'), postgresql_include=[], postgresql_nulls_not_distinct=False)
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
@ -0,0 +1,32 @@
|
||||
"""added environments and states to the db schema
|
||||
|
||||
Revision ID: 0a912926be8b
|
||||
Revises: 7eb66922e256
|
||||
Create Date: 2026-02-08 20:51:10.862477
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '0a912926be8b'
|
||||
down_revision: Union[str, Sequence[str], None] = '7eb66922e256'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
# ### end Alembic commands ###
|
||||
@ -5,32 +5,17 @@ from sqlalchemy import Column, UUID, String, ForeignKey, UniqueConstraint, Boole
|
||||
|
||||
class Pillar(Base):
|
||||
"""
|
||||
Describes a pillar by its name and parent. A parent equal to NULL mains that the pillar is a top level pillar.
|
||||
Note that this is not a value, as the value is bound to the host.
|
||||
A value for a given pillar on a given host.
|
||||
"""
|
||||
__tablename__ = 'pillar_tool_pillar'
|
||||
id = Column(UUID, primary_key=True)
|
||||
name = Column(String, nullable=False)
|
||||
parent_id = Column(UUID, ForeignKey('pillar_tool_pillar.id'), nullable=True)
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint('parent_id', 'name', name="pillar_parent_unique_name_parent"),
|
||||
)
|
||||
|
||||
|
||||
class PillarValue(Base):
|
||||
"""
|
||||
A value for a given pillar on a given host.
|
||||
"""
|
||||
__tablename__ = 'pillar_tool_pillar_value'
|
||||
id = Column(UUID, primary_key=True)
|
||||
pillar_id = Column(UUID, ForeignKey('pillar_tool_pillar.id'), nullable=False)
|
||||
pillar_name = Column(String, nullable=False)
|
||||
host_id = Column(UUID, ForeignKey('pillar_tool_host.id'), nullable=True)
|
||||
type = Column(String, nullable=False)
|
||||
value = Column(String, nullable=False)
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint('pillar_id', 'host_id', name='pillar_value_unique_pillar_value'),
|
||||
UniqueConstraint('pillar_name', 'host_id', name='pillar_unique_pillar_name'),
|
||||
)
|
||||
|
||||
|
||||
|
||||
39
pillar_tool/db/models/top_data.py
Normal file
39
pillar_tool/db/models/top_data.py
Normal file
@ -0,0 +1,39 @@
|
||||
from pillar_tool.db.base_model import Base
|
||||
|
||||
from sqlalchemy import Column, UUID, String, ForeignKey, UniqueConstraint, Boolean
|
||||
import uuid
|
||||
|
||||
|
||||
class Environment(Base):
|
||||
__tablename__ = "pillar_tool_environment"
|
||||
|
||||
id = Column(UUID, primary_key=True, default=uuid.uuid4)
|
||||
name = Column(String, nullable=False)
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint('name', name="pillar_tool_unique_environment_unique_name")
|
||||
)
|
||||
|
||||
|
||||
class State(Base):
|
||||
__tablename__ = "pillar_tool_state"
|
||||
|
||||
id = Column(UUID, primary_key=True, default=uuid.uuid4)
|
||||
name = Column(String, nullable=False)
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint('name', name="pillar_tool_unique_state_unique_name")
|
||||
)
|
||||
|
||||
|
||||
class StateAssignment(Base):
|
||||
__tablename__ = "pillar_tool_state_assignment"
|
||||
|
||||
id = Column(UUID, primary_key=True, default=uuid.uuid4)
|
||||
environment_id = Column(UUID, ForeignKey("pillar_tool_environment.id"), nullable=False)
|
||||
state_id = Column(UUID, ForeignKey("pillar_tool_state.id"), nullable=False)
|
||||
host_id = Column(UUID, ForeignKey("pillar_tool_host.id"), nullable=False)
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint('environment_id', 'state_id', 'host_id', name="pillar_tool_state_assignment_unique_env_state_host"),
|
||||
)
|
||||
@ -23,7 +23,7 @@ def generate_host_hierarchy(db: Session, labels: list[str]) -> list[Host]:
|
||||
# NOTE: this is an assertion because the schema should enforce this
|
||||
assert len(result) == 1
|
||||
instance = Host(result[0])
|
||||
print(instance.id)
|
||||
last_parent_id = instance.id
|
||||
out.append(instance)
|
||||
|
||||
return out
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
# load config so everything else can work
|
||||
from pillar_tool.util import load_config, config
|
||||
load_config()
|
||||
|
||||
from http.server import BaseHTTPRequestHandler
|
||||
|
||||
from pillar_tool.db.base_model import as_dict
|
||||
from pillar_tool.middleware.logging import request_logging_middleware
|
||||
from pillar_tool.schemas import HostCreateParams
|
||||
from pillar_tool.util import load_config, config
|
||||
load_config()
|
||||
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
|
||||
@ -84,17 +85,42 @@ async def pillar_get(req: Request, host: str):
|
||||
|
||||
@app.post("/pillar/{host}")
|
||||
async def pillar_set(request: Request, host: str, value: str):
|
||||
print(request.headers)
|
||||
return JSONResponse({
|
||||
"captain.linvogel.internal": {
|
||||
"states": ["state1", "state2"],
|
||||
"test": {
|
||||
"pillar": "value"
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@app.get("/hosts")
|
||||
async def host_list(request: Request):
|
||||
all_hosts = list_all_hosts(request.state.db)
|
||||
return JSONResponse([as_dict(x) for x in all_hosts])
|
||||
return JSONResponse([x.name for x in all_hosts if x.parent_id is None])
|
||||
|
||||
@app.get("/hostgroups")
|
||||
async def hostgroup_list(request: Request):
|
||||
all_hosts = list_all_hosts(request.state.db)
|
||||
return JSONResponse([x.name for x in all_hosts if x.parent_id is not None])
|
||||
|
||||
@app.post("/host/{fqdn}")
|
||||
async def host_add(request: Request, fqdn: str, params: HostCreateParams):
|
||||
new_host = create_host(request.state.db, fqdn, params.parent)
|
||||
|
||||
output = {
|
||||
"message": "Host created",
|
||||
"host": new_host,
|
||||
}
|
||||
if params.parent:
|
||||
print(f"Created new host: {new_host} with parent: {params.parent}")
|
||||
else:
|
||||
print(f"Created new host: {new_host}")
|
||||
output.update({
|
||||
"parent": params.parent
|
||||
})
|
||||
|
||||
return JSONResponse(output)
|
||||
|
||||
@app.get("/top/{fqdn}")
|
||||
async def host_top(request: Request, fqdn: str):
|
||||
# TODO: implement
|
||||
return JSONResponse({})
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user