Skip to content

Commit 860f42f

Browse files
committed
Use foreign key to api key object from all child objects
Issue #75
1 parent b3ad4ea commit 860f42f

31 files changed

+235
-27
lines changed
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
"""Add foreign key to each object table to link to api id row
2+
3+
Revision ID: 9afeb4e61715
4+
Revises: 39e8a680df30
5+
Create Date: 2023-05-08 12:24:21.494334
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
from sqlalchemy.dialects import mysql
11+
12+
# revision identifiers, used by Alembic.
13+
revision = '9afeb4e61715'
14+
down_revision = '39e8a680df30'
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade() -> None:
20+
# ### commands auto generated by Alembic - please adjust! ###
21+
op.add_column('agent', sa.Column('api_id_fk', sa.Integer(), nullable=True))
22+
op.create_foreign_key(None, 'agent', 'api_id', ['api_id_fk'], ['id'])
23+
op.add_column('agent_pool', sa.Column('api_id_fk', sa.Integer(), nullable=True))
24+
op.create_foreign_key(None, 'agent_pool', 'api_id', ['api_id_fk'], ['id'])
25+
op.add_column('agent_token', sa.Column('api_id_fk', sa.Integer(), nullable=True))
26+
op.create_foreign_key(None, 'agent_token', 'api_id', ['api_id_fk'], ['id'])
27+
op.drop_index('_api_id_suffix_index', table_name='api_id')
28+
op.drop_index('_object_class_object_id_in', table_name='api_id')
29+
op.drop_index('_object_class_object_id_uc', table_name='api_id')
30+
op.drop_column('api_id', 'object_class')
31+
op.drop_column('api_id', 'object_id')
32+
op.add_column('apply', sa.Column('api_id_fk', sa.Integer(), nullable=True))
33+
op.create_foreign_key(None, 'apply', 'api_id', ['api_id_fk'], ['id'])
34+
op.add_column('audit_event', sa.Column('api_id_fk', sa.Integer(), nullable=True))
35+
op.create_foreign_key(None, 'audit_event', 'api_id', ['api_id_fk'], ['id'])
36+
op.add_column('authorised_repo', sa.Column('api_id_fk', sa.Integer(), nullable=True))
37+
op.create_foreign_key(None, 'authorised_repo', 'api_id', ['api_id_fk'], ['id'])
38+
op.add_column('blob', sa.Column('api_id_fk', sa.Integer(), nullable=True))
39+
op.create_foreign_key(None, 'blob', 'api_id', ['api_id_fk'], ['id'])
40+
op.add_column('configuration_version', sa.Column('api_id_fk', sa.Integer(), nullable=True))
41+
op.create_foreign_key(None, 'configuration_version', 'api_id', ['api_id_fk'], ['id'])
42+
op.add_column('environment', sa.Column('api_id_fk', sa.Integer(), nullable=True))
43+
op.create_foreign_key(None, 'environment', 'api_id', ['api_id_fk'], ['id'])
44+
op.add_column('github_app_oauth_token', sa.Column('api_id_fk', sa.Integer(), nullable=True))
45+
op.create_foreign_key(None, 'github_app_oauth_token', 'api_id', ['api_id_fk'], ['id'])
46+
op.add_column('lifecycle', sa.Column('api_id_fk', sa.Integer(), nullable=True))
47+
op.create_foreign_key(None, 'lifecycle', 'api_id', ['api_id_fk'], ['id'])
48+
op.add_column('oauth_client', sa.Column('api_id_fk', sa.Integer(), nullable=True))
49+
op.create_foreign_key(None, 'oauth_client', 'api_id', ['api_id_fk'], ['id'])
50+
op.add_column('oauth_token', sa.Column('api_id_fk', sa.Integer(), nullable=True))
51+
op.create_foreign_key(None, 'oauth_token', 'api_id', ['api_id_fk'], ['id'])
52+
op.add_column('organisation', sa.Column('api_id_fk', sa.Integer(), nullable=True))
53+
op.create_foreign_key(None, 'organisation', 'api_id', ['api_id_fk'], ['id'])
54+
op.add_column('plan', sa.Column('api_id_fk', sa.Integer(), nullable=True))
55+
op.create_foreign_key(None, 'plan', 'api_id', ['api_id_fk'], ['id'])
56+
op.add_column('project', sa.Column('api_id_fk', sa.Integer(), nullable=True))
57+
op.create_foreign_key(None, 'project', 'api_id', ['api_id_fk'], ['id'])
58+
op.add_column('run', sa.Column('api_id_fk', sa.Integer(), nullable=True))
59+
op.create_foreign_key(None, 'run', 'api_id', ['api_id_fk'], ['id'])
60+
op.add_column('run_queue', sa.Column('api_id_fk', sa.Integer(), nullable=True))
61+
op.create_foreign_key(None, 'run_queue', 'api_id', ['api_id_fk'], ['id'])
62+
op.add_column('state_version', sa.Column('api_id_fk', sa.Integer(), nullable=True))
63+
op.create_foreign_key(None, 'state_version', 'api_id', ['api_id_fk'], ['id'])
64+
op.add_column('tag', sa.Column('api_id_fk', sa.Integer(), nullable=True))
65+
op.create_foreign_key(None, 'tag', 'api_id', ['api_id_fk'], ['id'])
66+
op.add_column('task', sa.Column('api_id_fk', sa.Integer(), nullable=True))
67+
op.create_foreign_key(None, 'task', 'api_id', ['api_id_fk'], ['id'])
68+
op.add_column('task_result', sa.Column('api_id_fk', sa.Integer(), nullable=True))
69+
op.create_foreign_key(None, 'task_result', 'api_id', ['api_id_fk'], ['id'])
70+
op.add_column('task_stage', sa.Column('api_id_fk', sa.Integer(), nullable=True))
71+
op.create_foreign_key(None, 'task_stage', 'api_id', ['api_id_fk'], ['id'])
72+
op.add_column('team', sa.Column('api_id_fk', sa.Integer(), nullable=True))
73+
op.create_foreign_key(None, 'team', 'api_id', ['api_id_fk'], ['id'])
74+
op.add_column('team_workspace_access', sa.Column('api_id_fk', sa.Integer(), nullable=True))
75+
op.create_foreign_key(None, 'team_workspace_access', 'api_id', ['api_id_fk'], ['id'])
76+
op.add_column('user', sa.Column('api_id_fk', sa.Integer(), nullable=True))
77+
op.create_foreign_key(None, 'user', 'api_id', ['api_id_fk'], ['id'])
78+
op.add_column('user_token', sa.Column('api_id_fk', sa.Integer(), nullable=True))
79+
op.create_foreign_key(None, 'user_token', 'api_id', ['api_id_fk'], ['id'])
80+
op.add_column('workspace', sa.Column('api_id_fk', sa.Integer(), nullable=True))
81+
op.create_foreign_key(None, 'workspace', 'api_id', ['api_id_fk'], ['id'])
82+
op.add_column('workspace_task', sa.Column('api_id_fk', sa.Integer(), nullable=True))
83+
op.create_foreign_key(None, 'workspace_task', 'api_id', ['api_id_fk'], ['id'])
84+
# ### end Alembic commands ###
85+
86+
87+
def downgrade() -> None:
88+
# ### commands auto generated by Alembic - please adjust! ###
89+
op.drop_constraint(None, 'workspace_task', type_='foreignkey')
90+
op.drop_column('workspace_task', 'api_id_fk')
91+
op.drop_constraint(None, 'workspace', type_='foreignkey')
92+
op.drop_column('workspace', 'api_id_fk')
93+
op.drop_constraint(None, 'user_token', type_='foreignkey')
94+
op.drop_column('user_token', 'api_id_fk')
95+
op.drop_constraint(None, 'user', type_='foreignkey')
96+
op.drop_column('user', 'api_id_fk')
97+
op.drop_constraint(None, 'team_workspace_access', type_='foreignkey')
98+
op.drop_column('team_workspace_access', 'api_id_fk')
99+
op.drop_constraint(None, 'team', type_='foreignkey')
100+
op.drop_column('team', 'api_id_fk')
101+
op.drop_constraint(None, 'task_stage', type_='foreignkey')
102+
op.drop_column('task_stage', 'api_id_fk')
103+
op.drop_constraint(None, 'task_result', type_='foreignkey')
104+
op.drop_column('task_result', 'api_id_fk')
105+
op.drop_constraint(None, 'task', type_='foreignkey')
106+
op.drop_column('task', 'api_id_fk')
107+
op.drop_constraint(None, 'tag', type_='foreignkey')
108+
op.drop_column('tag', 'api_id_fk')
109+
op.drop_constraint(None, 'state_version', type_='foreignkey')
110+
op.drop_column('state_version', 'api_id_fk')
111+
op.drop_constraint(None, 'run_queue', type_='foreignkey')
112+
op.drop_column('run_queue', 'api_id_fk')
113+
op.drop_constraint(None, 'run', type_='foreignkey')
114+
op.drop_column('run', 'api_id_fk')
115+
op.drop_constraint(None, 'project', type_='foreignkey')
116+
op.drop_column('project', 'api_id_fk')
117+
op.drop_constraint(None, 'plan', type_='foreignkey')
118+
op.drop_column('plan', 'api_id_fk')
119+
op.drop_constraint(None, 'organisation', type_='foreignkey')
120+
op.drop_column('organisation', 'api_id_fk')
121+
op.drop_constraint(None, 'oauth_token', type_='foreignkey')
122+
op.drop_column('oauth_token', 'api_id_fk')
123+
op.drop_constraint(None, 'oauth_client', type_='foreignkey')
124+
op.drop_column('oauth_client', 'api_id_fk')
125+
op.drop_constraint(None, 'lifecycle', type_='foreignkey')
126+
op.drop_column('lifecycle', 'api_id_fk')
127+
op.drop_constraint(None, 'github_app_oauth_token', type_='foreignkey')
128+
op.drop_column('github_app_oauth_token', 'api_id_fk')
129+
op.drop_constraint(None, 'environment', type_='foreignkey')
130+
op.drop_column('environment', 'api_id_fk')
131+
op.drop_constraint(None, 'configuration_version', type_='foreignkey')
132+
op.drop_column('configuration_version', 'api_id_fk')
133+
op.drop_constraint(None, 'blob', type_='foreignkey')
134+
op.drop_column('blob', 'api_id_fk')
135+
op.drop_constraint(None, 'authorised_repo', type_='foreignkey')
136+
op.drop_column('authorised_repo', 'api_id_fk')
137+
op.drop_constraint(None, 'audit_event', type_='foreignkey')
138+
op.drop_column('audit_event', 'api_id_fk')
139+
op.drop_constraint(None, 'apply', type_='foreignkey')
140+
op.drop_column('apply', 'api_id_fk')
141+
op.add_column('api_id', sa.Column('object_id', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True))
142+
op.add_column('api_id', sa.Column('object_class', mysql.VARCHAR(length=128), nullable=True))
143+
op.create_index('_object_class_object_id_uc', 'api_id', ['object_class', 'object_id'], unique=False)
144+
op.create_index('_object_class_object_id_in', 'api_id', ['object_class', 'object_id'], unique=False)
145+
op.create_index('_api_id_suffix_index', 'api_id', ['api_id_suffix'], unique=False)
146+
op.drop_constraint(None, 'agent_token', type_='foreignkey')
147+
op.drop_column('agent_token', 'api_id_fk')
148+
op.drop_constraint(None, 'agent_pool', type_='foreignkey')
149+
op.drop_column('agent_pool', 'api_id_fk')
150+
op.drop_constraint(None, 'agent', type_='foreignkey')
151+
op.drop_column('agent', 'api_id_fk')
152+
# ### end Alembic commands ###

terrarun/models/agent.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class Agent(Base, BaseObject):
3333

3434
__tablename__ = "agent"
3535
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
36+
api_id_fk = sqlalchemy.Column(sqlalchemy.ForeignKey("api_id.id"), nullable=True)
37+
api_id_obj = sqlalchemy.orm.relation("ApiId", foreign_keys=[api_id_fk])
38+
3639
name = sqlalchemy.Column(terrarun.database.Database.GeneralString, default=None)
3740
created_at = sqlalchemy.Column(sqlalchemy.DateTime, default=sqlalchemy.sql.func.now())
3841

terrarun/models/agent_pool.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ class AgentPool(Base, BaseObject):
2424
name = sqlalchemy.Column(terrarun.database.Database.GeneralString, default=None)
2525
created_at = sqlalchemy.Column(sqlalchemy.DateTime, default=sqlalchemy.sql.func.now())
2626

27+
api_id_fk = sqlalchemy.Column(sqlalchemy.ForeignKey("api_id.id"), nullable=True)
28+
api_id_obj = sqlalchemy.orm.relation("ApiId", foreign_keys=[api_id_fk])
29+
2730
organisation_id = sqlalchemy.Column(sqlalchemy.ForeignKey("organisation.id"), nullable=True)
2831
organisation = sqlalchemy.orm.relationship("Organisation")
2932

terrarun/models/agent_token.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ class AgentToken(Base, BaseObject):
2020

2121
__tablename__ = "agent_token"
2222
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
23+
api_id_fk = sqlalchemy.Column(sqlalchemy.ForeignKey("api_id.id"), nullable=True)
24+
api_id_obj = sqlalchemy.orm.relation("ApiId", foreign_keys=[api_id_fk])
25+
2326
description = sqlalchemy.Column(terrarun.database.Database.GeneralString, default=None)
2427
created_at = sqlalchemy.Column(sqlalchemy.DateTime, default=sqlalchemy.sql.func.now())
2528
last_used_at = sqlalchemy.Column(sqlalchemy.DateTime, default=None)

terrarun/models/api_id.py

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,6 @@ class ApiId(Base):
1414

1515
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
1616
api_id_suffix = sqlalchemy.Column(terrarun.database.Database.GeneralString, unique=True)
17-
object_class = sqlalchemy.Column(terrarun.database.Database.GeneralString)
18-
object_id = sqlalchemy.Column(sqlalchemy.Integer)
19-
20-
__table_args__ = (
21-
sqlalchemy.UniqueConstraint('object_class', 'object_id', name='_object_class_object_id_uc'),
22-
sqlalchemy.Index('_object_class_object_id_in', 'object_class', 'object_id'),
23-
sqlalchemy.Index('_api_id_suffix_index', 'api_id_suffix'),
24-
)
2517

2618
@classmethod
2719
def _generate_api_id(cls):
@@ -40,43 +32,31 @@ def get_db_id_from_api_id(cls, target_class, api_id):
4032
return None
4133

4234
session = Database.get_session()
43-
res = session.query(cls).filter(
44-
cls.object_class==target_class.__name__,
35+
res = session.query(target_class).join(cls).filter(
4536
cls.api_id_suffix==stripped_id
4637
).first()
4738
if not res:
4839
return None
4940

50-
return res.object_id
41+
return res.id
5142

5243
@classmethod
5344
def get_api_id(cls, obj):
5445
"""Return api ID for given object"""
55-
if not 'id' in dir(obj) or not obj.id:
56-
raise Exception("Object does not have an ID")
57-
5846
if not 'ID_PREFIX' in dir(obj) or not obj.ID_PREFIX:
5947
raise Exception("Object does not have an ID prefix")
6048

6149
session = Database.get_session()
6250

63-
object_class = obj.__class__.__name__
64-
object_id = obj.id
65-
66-
api_id_object = session.query(cls).filter(
67-
cls.object_class==object_class,
68-
cls.object_id==object_id
69-
).first()
70-
71-
if not api_id_object:
51+
if obj.api_id_obj is None:
7252
api_id_object = cls(
73-
object_class=object_class,
74-
object_id=object_id,
7553
api_id_suffix=cls._generate_api_id()
7654
)
7755
session.add(api_id_object)
56+
obj.api_id_obj = api_id_object
57+
session.add(api_id_object)
7858
session.commit()
7959

80-
return f"{obj.ID_PREFIX}-{api_id_object.api_id_suffix}"
60+
return f"{obj.ID_PREFIX}-{obj.api_id_obj.api_id_suffix}"
8161

8262

terrarun/models/apply.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ class Apply(TerraformCommand, Base):
2020
__tablename__ = 'apply'
2121
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
2222

23+
api_id_fk = sqlalchemy.Column(sqlalchemy.ForeignKey("api_id.id"), nullable=True)
24+
api_id_obj = sqlalchemy.orm.relation("ApiId", foreign_keys=[api_id_fk])
25+
2326
plan_id = sqlalchemy.Column(sqlalchemy.ForeignKey("plan.id"), nullable=False)
2427
plan = sqlalchemy.orm.relationship("Plan", back_populates="applies")
2528

terrarun/models/audit_event.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ class AuditEvent(Base, BaseObject):
3030
__tablename__ = 'audit_event'
3131

3232
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
33+
api_id_fk = sqlalchemy.Column(sqlalchemy.ForeignKey("api_id.id"), nullable=True)
34+
api_id_obj = sqlalchemy.orm.relation("ApiId", foreign_keys=[api_id_fk])
35+
3336
timestamp = sqlalchemy.Column(sqlalchemy.DateTime, default=sqlalchemy.sql.func.now())
3437

3538
organisation_id = sqlalchemy.Column(sqlalchemy.ForeignKey("organisation.id"), nullable=False)

terrarun/models/authorised_repo.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ class AuthorisedRepo(Base, BaseObject):
2121
__tablename__ = 'authorised_repo'
2222

2323
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
24+
api_id_fk = sqlalchemy.Column(sqlalchemy.ForeignKey("api_id.id"), nullable=True)
25+
api_id_obj = sqlalchemy.orm.relation("ApiId", foreign_keys=[api_id_fk])
2426

2527
created_at = sqlalchemy.Column(sqlalchemy.DateTime, default=sqlalchemy.sql.func.now())
2628

terrarun/models/blob.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,9 @@ class Blob(Base, BaseObject):
1616

1717
__tablename__ = 'blob'
1818
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
19+
20+
api_id_fk = sqlalchemy.Column(sqlalchemy.ForeignKey("api_id.id"), nullable=True)
21+
api_id_obj = sqlalchemy.orm.relation("ApiId", foreign_keys=[api_id_fk])
22+
1923
# Create blob of 200MB
2024
data = sqlalchemy.Column(sqlalchemy.LargeBinary(length=((2**20) * 200)))

terrarun/models/configuration.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ class ConfigurationVersion(Base, BaseObject):
3232
ID_PREFIX = 'cv'
3333

3434
__tablename__ = 'configuration_version'
35+
3536
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
37+
api_id_fk = sqlalchemy.Column(sqlalchemy.ForeignKey("api_id.id"), nullable=True)
38+
api_id_obj = sqlalchemy.orm.relation("ApiId", foreign_keys=[api_id_fk])
3639

3740
workspace_id = sqlalchemy.Column(sqlalchemy.ForeignKey("workspace.id"), nullable=False)
3841
workspace = sqlalchemy.orm.relationship("Workspace", back_populates="configuration_versions")

0 commit comments

Comments
 (0)