def upgrade(): op.create_table( 'networks', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('name', sa.String, unique=True, nullable=False), sa.Column('current_task_id', sau.UUIDType, sa.ForeignKey('tasks.id')), sa.Column('port_group', sa.String, unique=True, nullable=False), sa.Column('gateway', sau.IPAddressType, nullable=False), sa.Column('dns_servers', sa.ARRAY(sau.IPAddressType), nullable=False), sa.Column('region_id', sau.UUIDType, sa.ForeignKey('regions.id', ondelete='RESTRICT'), nullable=False), sa.Column('state', sa.Enum(NetworkState), default=NetworkState.CREATING, nullable=False), sa.Column('cidr', IPv4Network, nullable=False), sa.Column('pool_start', sau.IPAddressType, nullable=False), sa.Column('pool_end', sau.IPAddressType, nullable=False), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False), )
def upgrade(): op.create_table( 'network_ports', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('network_id', sau.UUIDType, sa.ForeignKey('networks.id', ondelete='RESTRICT'), nullable=False), sa.Column('project_id', sau.UUIDType, sa.ForeignKey('projects.id', ondelete='CASCADE'), nullable=False, index=True), sa.Column('ip_address', sau.IPAddressType), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False))
def upgrade(): op.create_table( 'images', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('name', sa.String, nullable=False), sa.Column('file_name', sa.String, unique=True, nullable=False), sa.Column('locked', sa.Boolean, default=False, nullable=False), sa.Column('state', sa.Enum(ImageState), default=ImageState.CREATING, nullable=False), sa.Column('visibility', sa.Enum(ImageVisibility), default=ImageVisibility.PRIVATE, nullable=False), sa.Column('project_id', sau.UUIDType, sa.ForeignKey('projects.id', ondelete='RESTRICT'), nullable=False), sa.Column('region_id', sau.UUIDType, sa.ForeignKey('regions.id', ondelete='RESTRICT'), nullable=False), sa.Column('current_task_id', sau.UUIDType, sa.ForeignKey('tasks.id')), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False), ) op.create_table( 'image_members', sa.Column('image_id', sau.UUIDType, sa.ForeignKey('images.id', ondelete='CASCADE'), nullable=False, primary_key=True), sa.Column('project_id', sau.UUIDType, sa.ForeignKey('projects.id', ondelete='CASCADE'), nullable=False, primary_key=True), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), )
class TimestampMixin(object): created_at = db.Column(sau.ArrowType(), nullable=False, index=True, default=arrow.utcnow) updated_at = db.Column(sau.ArrowType(), nullable=False, index=True, default=arrow.utcnow, onupdate=arrow.utcnow)
def upgrade(): op.create_table( 'projects', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('name', sa.String, unique=True, nullable=False), sa.Column('state', sa.Enum(ProjectState), default=ProjectState.CREATED, nullable=False), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False) )
def upgrade(): op.create_table( 'tasks', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('name', sa.String, nullable=False), sa.Column('state', sa.Enum(TaskState), default=TaskState.PENDING, nullable=False), sa.Column('error_message', sa.Text), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False), sa.Column('stopped_at', sau.ArrowType(timezone=True)), )
def upgrade(): op.create_table( 'instances', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('name', sa.String, nullable=False), sa.Column('tags', HSTORE), sa.Column('state', sa.Enum(InstanceState), default=InstanceState.BUILDING, nullable=False), sa.Column('network_port_id', sau.UUIDType, sa.ForeignKey('network_ports.id', ondelete='RESTRICT'), index=True), sa.Column('region_id', sau.UUIDType, sa.ForeignKey('regions.id', ondelete='RESTRICT'), nullable=False), sa.Column('zone_id', sau.UUIDType, sa.ForeignKey('zones.id', ondelete='RESTRICT')), sa.Column('service_account_id', sau.UUIDType, sa.ForeignKey('authn_service_accounts.id', ondelete='RESTRICT'), nullable=False), sa.Column('project_id', sau.UUIDType, sa.ForeignKey('projects.id', ondelete='RESTRICT'), nullable=False), sa.Column('current_task_id', sau.UUIDType, sa.ForeignKey('tasks.id')), sa.Column('image_id', sau.UUIDType, sa.ForeignKey('images.id', ondelete='SET NULL')), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False), )
def upgrade(): op.create_table( 'keypairs', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('name', sa.String, nullable=False), sa.Column('public_key', sa.Text, nullable=False), sa.Column('project_id', sau.UUIDType, sa.ForeignKey('projects.id', ondelete='CASCADE'), nullable=False), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False)) op.create_table( 'instance_keypairs', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('keypair_id', sau.UUIDType, sa.ForeignKey('keypairs.id', ondelete='CASCADE')), sa.Column('instance_id', sau.UUIDType, sa.ForeignKey('instances.id', ondelete='CASCADE')), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False))
def upgrade(): op.create_table( 'authn_users', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('username', sa.String, nullable=False), sa.Column('driver', sa.String, nullable=False), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False)) op.create_unique_constraint('uq_username_driver', 'authn_users', ['username', 'driver'])
class Tester(SQLAlchemyJsonMixin, Base): __tablename__ = 'tester' intField = sqlalchemy.Column(sqlalchemy.BigInteger(), primary_key=True) strField = sqlalchemy.Column(sqlalchemy.UnicodeText()) noneField = sqlalchemy.Column(sqlalchemy.Integer()) floatField = sqlalchemy.Column(sqlalchemy.Float()) boolField = sqlalchemy.Column(sqlalchemy.Boolean()) dateTimeField = sqlalchemy.Column(sqlalchemy.DateTime()) arrowField = sqlalchemy.Column(sqlalchemy_utils.ArrowType()) relFieldId = sqlalchemy.Column( sqlalchemy.BigInteger(), sqlalchemy.ForeignKey('submodel.id')) relField = sqlalchemy.orm.relationship('SubModel')
def upgrade(): op.create_table( 'builtin_users', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('username', sa.String, nullable=False, unique=True), sa.Column('password', sau.PasswordType(schemes=['bcrypt']), nullable=False), sa.Column('roles', ARRAY(sa.String), default=list), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False))
def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.create_table('resources', sa.Column('created_at', sau.ArrowType(), nullable=False), sa.Column('updated_at', sau.ArrowType(), nullable=False), sa.Column('id', sa.BigInteger(), nullable=False), sa.Column('category_id', sa.BigInteger(), nullable=False), sa.Column('user_id', sa.BigInteger(), nullable=False), sa.Column('type', sa.String(8), nullable=True), sa.Column('quantity_available', sa.BigInteger(), nullable=True), sa.Column('quantity_needed', sa.BigInteger(), nullable=True), sa.Column('fulfilled', sa.Boolean(), server_default='0', nullable=False), sa.ForeignKeyConstraint(['category_id'], ['categories.id'], onupdate='CASCADE', ondelete='RESTRICT'), sa.ForeignKeyConstraint(['user_id'], ['users.id'], onupdate='CASCADE', ondelete='CASCADE'), sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_resources_created_at'), 'resources', ['created_at'], unique=False) op.create_index(op.f('ix_resources_type'), 'resources', ['type'], unique=False) op.create_index(op.f('ix_resources_updated_at'), 'resources', ['updated_at'], unique=False) op.drop_constraint('user_resource_fulfillment_ibfk_2', 'user_resource_fulfillment', type_='foreignkey') op.drop_constraint('user_resource_fulfillment_ibfk_1', 'user_resource_fulfillment', type_='foreignkey') op.drop_table('user_resources') op.create_foreign_key('fk_urf_resources_fulfilling', 'user_resource_fulfillment', 'resources', ['fulfilling_resource_id'], ['id'], onupdate='CASCADE', ondelete='RESTRICT') op.create_foreign_key('fk_urf_resources_fulfilled', 'user_resource_fulfillment', 'resources', ['fulfilled_resource_id'], ['id'], onupdate='CASCADE', ondelete='RESTRICT')
def upgrade(): policies_table = op.create_table( 'authz_policies', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('name', sa.String, nullable=False, unique=True), sa.Column('description', sa.String), sa.Column('tags', sa.ARRAY(sa.String)), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False)) roles_table = op.create_table( 'authz_roles', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('name', sa.String, nullable=False), sa.Column('project_id', sau.UUIDType, sa.ForeignKey('projects.id', ondelete='CASCADE')), sa.Column('description', sa.String), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False)) op.create_unique_constraint('uq_name_project_id', 'authz_roles', ['name', 'project_id']) role_policies_table = op.create_table( 'authz_role_policies', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('role_id', sau.UUIDType, sa.ForeignKey('authz_roles.id', ondelete='CASCADE'), index=True, nullable=False), sa.Column('policy_id', sau.UUIDType, sa.ForeignKey('authz_policies.id', ondelete='CASCADE'), index=True, nullable=False), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False)) op.create_table( 'authn_service_accounts', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('name', sa.String, nullable=False), sa.Column('project_id', sau.UUIDType, sa.ForeignKey('projects.id', ondelete='CASCADE'), nullable=False), sa.Column('role_id', sau.UUIDType, sa.ForeignKey('authz_roles.id', ondelete='RESTRICT'), nullable=False), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False)) # TODO: add project_members op.create_table( 'project_members', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('user_id', sau.UUIDType, sa.ForeignKey('authn_users.id', ondelete='CASCADE'), nullable=False, index=True), sa.Column('project_id', sau.UUIDType, sa.ForeignKey('projects.id', ondelete='CASCADE'), nullable=False, index=True), sa.Column('role_id', sau.UUIDType, sa.ForeignKey('authz_roles.id', ondelete='RESTRICT'), nullable=False, index=True), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False)) op.bulk_insert(roles_table, [{ "name": "admin", "description": "Administrator Role" }, { "name": "viewer", "description": "Viewer role; has the ability to view non-project level objects" }]) # Policy Tags: # viewer - policies the viewer role should have # project_member - policies the default project member role should have # service_account - policies the default project service account role should have op.bulk_insert( policies_table, [ # Policies { "name": "policies:create", "description": "Ability to create a policy", }, { "name": "policies:get", "description": "Ability to get a policy", "tags": ["viewer"] }, { "name": "policies:update", "description": "Ability to update a policy" }, { "name": "policies:list", "description": "Ability to list policies", "tags": ["viewer"] }, { "name": "policies:delete", "description": "Ability to delete a policy" }, # Roles { "name": "roles:create:global", "description": "Ability to create a global role" }, { "name": "roles:delete:global", "description": "Ability to delete a global role" }, { "name": "roles:create:project", "description": "Ability to create a project role", "tags": ["project_member"] }, { "name": "roles:delete:project", "description": "Ability to delete a project role", "tags": ["project_member"] }, { "name": "roles:get", "description": "Ability to get a role", "tags": ["viewer"] }, { "name": "roles:list", "description": "Ability to list roles", "tags": ["viewer"] }, # Regions { "name": "regions:create", "description": "Ability to create a region" }, { "name": "regions:get", "description": "Ability to get a region", "tags": ["viewer"] }, { "name": "regions:list", "description": "Ability to list regions", "tags": ["viewer"] }, { "name": "regions:delete", "description": "Ability to delete a region" }, { "name": "regions:action:schedule", "description": "Ability to change the schedule mode of the region" }, # Zones { "name": "zones:create", "description": "Ability to create a zone" }, { "name": "zones:get", "description": "Ability to get a zone", "tags": ["viewer"] }, { "name": "zones:list", "description": "Ability to list zones", "tags": ["viewer"] }, { "name": "zones:delete", "description": "Ability to delete a zone" }, { "name": "zones:action:schedule", "description": "Ability to change the schedule mode of the zone" }, # Projects { "name": "projects:create", "description": "Ability to create a project" }, { "name": "projects:get", "description": "Ability to get a project", "tags": ["viewer"] }, { "name": "projects:list", "description": "Ability to list projects", "tags": ["viewer"] }, { "name": "projects:delete", "description": "Ability to delete a project" }, # TODO: add policies for project:members # Tasks # Images { "name": "images:create", "description": "Ability to create an image", "tags": ["project_member"] }, { "name": "images:create:public", "description": "Ability to create a public image" }, { "name": "images:get", "description": "Ability to get an image", "tags": ["project_member", "service_account"] }, { "name": "images:list", "description": "Ability to list images", "tags": ["project_member", "service_account"] }, { "name": "images:delete", "description": "Ability to delete an image", "tags": ["project_member"] }, { "name": "images:action:lock", "description": "Ability to lock an image", "tags": ["project_member"] }, { "name": "images:action:unlock", "description": "Ability to unlock an image", "tags": ["project_member"] }, # Instances { "name": "instances:create", "description": "Ability to create an instance", "tags": ["project_member"] }, { "name": "instances:get", "description": "Ability to get an instance", "tags": ["project_member", "service_account"] }, { "name": "instances:list", "description": "Ability to list instances", "tags": ["project_member", "service_account"] }, { "name": "instances:delete", "description": "Ability to delete an instance", "tags": ["project_member"] }, { "name": "instances:action:stop", "description": "Ability to stop an instance", "tags": ["project_member"] }, { "name": "instances:action:start", "description": "Ability to start an instance", "tags": ["project_member"] }, { "name": "instances:action:restart", "description": "Ability to restart an instance", "tags": ["project_member"] }, { "name": "instances:action:image", "description": "Ability to create an image from an instance", "tags": ["project_member"] }, { "name": "instances:action:image:public", "description": "Ability to create a public image from an instance" }, { "name": "instances:action:reset_state", "description": "Ability to reset the state of an instance to error", "tags": ["project_member"] }, { "name": "instances:action:reset_state:active", "description": "Ability to reset the state of an instance to active", "tags": ["project_member"] }, # Networks { "name": "networks:create", "description": "Ability to create a network" }, { "name": "networks:get", "description": "Ability to get a network", "tags": ["viewer"] }, { "name": "networks:list", "description": "Ability to list networks", "tags": ["viewer"] }, { "name": "networks:delete", "description": "Ability to delete a network" }, # Service Accounts { "name": "service_accounts:create", "description": "Ability to create a service account", "tags": ["project_member"] }, { "name": "service_accounts:get", "description": "Ability to get a service account", "tags": ["project_member", "service_account"] }, { "name": "service_accounts:list", "description": "Ability to list service accounts", "tags": ["project_member", "service_account"] }, { "name": "service_accounts:delete", "description": "Ability to delete a service account", "tags": ["project_member"] }, # BuiltIn Users { "name": "builtin:users:create", "description": "Ability to create users", }, { "name": "builtin:users:get", "description": "Ability to get a user", "tags": ["viewer"] }, { "name": "builtin:users:list", "description": "Ability to list users", "tags": ["viewer"] }, { "name": "builtin:users:delete", "description": "Ability to delete a user" }, { "name": "builtin:users:password", "description": "Ability to change a user's password" }, { "name": "builtin:users:role:add", "description": "Ability to add a role to a user" }, { "name": "builtin:users:role:remove", "description": "Ability to remove a user from a role" }, # Keypairs { "name": "keypairs:create", "description": "Ability to create a keypair", "tags": ["project_member"] }, { "name": "keypairs:get", "description": "Ability to get a keypair", "tags": ["project_member", "service_account"] }, { "name": "keypairs:list", "description": "Ability to list keypairs", "tags": ["project_member", "service_account"] }, { "name": "keypairs:delete", "description": "Ability to delete a keypair", "tags": ["project_member"] }, # Network Ports { "name": "network_ports:get", "description": "Ability to get a network port", "tags": ["project_member", "service_account"] }, { "name": "network_ports:list", "description": "Ability to list network ports", "tags": ["project_member", "service_account"] }, { "name": "network_ports:delete", "description": "Ability to delete a network port", "tags": ["project_member"] } ], multiinsert=False # Needed so the list insert works correctly ) connection = op.get_bind() admin_role = connection.execute( roles_table.select().where(roles_table.c.name == "admin")).fetchone() viewer_role = connection.execute( roles_table.select().where(roles_table.c.name == "viewer")).fetchone() for policy in connection.execute(policies_table.select()): connection.execute(role_policies_table.insert().values( role_id=admin_role.id, policy_id=policy.id)) if policy.tags is not None: if 'viewer' in policy.tags: connection.execute(role_policies_table.insert().values( role_id=viewer_role.id, policy_id=policy.id))
def upgrade(): op.create_table( 'regions', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('name', sa.String, unique=True, nullable=False), sa.Column('datacenter', sa.String, unique=True, nullable=False), sa.Column('image_datastore', sa.String, nullable=False), sa.Column('image_folder', sa.String), sa.Column('schedulable', sa.Boolean, nullable=False), sa.Column('state', sa.Enum(RegionState), default=RegionState.CREATING, nullable=False), sa.Column('current_task_id', sau.UUIDType, sa.ForeignKey('tasks.id')), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False), ) op.create_table( 'zones', sa.Column('id', sau.UUIDType, server_default=sa.text("uuid_generate_v4()"), primary_key=True), sa.Column('name', sa.String, unique=True, nullable=False), sa.Column('region_id', sau.UUIDType, sa.ForeignKey('regions.id', ondelete='RESTRICT'), nullable=False), sa.Column('vm_cluster', sa.String, nullable=False), sa.Column('vm_datastore', sa.String, nullable=False), sa.Column('vm_folder', sa.String), sa.Column('core_provision_percent', sa.Integer, nullable=False), sa.Column('ram_provision_percent', sa.Integer, nullable=False), sa.Column('schedulable', sa.Boolean, nullable=False), sa.Column('state', sa.Enum(ZoneState), default=ZoneState.CREATING, nullable=False), sa.Column('current_task_id', sau.UUIDType, sa.ForeignKey('tasks.id')), sa.Column('created_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), nullable=False, index=True), sa.Column('updated_at', sau.ArrowType(timezone=True), server_default=sa.text('clock_timestamp()'), onupdate=sa.text('clock_timestamp()'), nullable=False), )
def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.create_table('resources', sa.Column('id', sa.BigInteger(), nullable=False), sa.Column('name', sa.UnicodeText(), nullable=True), sa.PrimaryKeyConstraint('id')) op.create_table( 'users', sa.Column('created_at', sau.ArrowType(), nullable=False), sa.Column('updated_at', sau.ArrowType(), nullable=False), sa.Column('id', sa.BigInteger(), nullable=False), sa.Column('name', sa.UnicodeText(), nullable=False), sa.Column('username', sa.Unicode(length=64), nullable=False), sa.Column('password', sa.UnicodeText(), nullable=False), sa.Column('email', sa.UnicodeText(), nullable=True), sa.Column('phone', sa.BigInteger(), nullable=True), sa.Column('secondary_phone', sa.BigInteger(), nullable=True), sa.Column('bio', sa.UnicodeText(), nullable=False), sa.Column('immigration_status', sa.String(length=32), nullable=True), sa.Column('primary_role', sa.String(length=32), nullable=True), sa.Column('language', sa.String(length=2), nullable=False), sa.Column('country', sa.String(length=2), nullable=False), sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('username')) op.create_index(op.f('ix_users_created_at'), 'users', ['created_at'], unique=False) op.create_index(op.f('ix_users_immigration_status'), 'users', ['immigration_status'], unique=False) op.create_index(op.f('ix_users_updated_at'), 'users', ['updated_at'], unique=False) op.create_table( 'user_resources', sa.Column('created_at', sau.ArrowType(), nullable=False), sa.Column('updated_at', sau.ArrowType(), nullable=False), sa.Column('id', sa.BigInteger(), nullable=False), sa.Column('resource_id', sa.BigInteger(), nullable=False), sa.Column('user_id', sa.BigInteger(), nullable=False), sa.Column('type', sa.String(length=8), nullable=True), sa.Column('quantity_available', sa.BigInteger(), nullable=True), sa.Column('quantity_needed', sa.BigInteger(), nullable=True), sa.Column('fulfilled', sa.Boolean(), server_default='0', nullable=False), sa.ForeignKeyConstraint(['resource_id'], ['resources.id'], onupdate='CASCADE', ondelete='RESTRICT'), sa.ForeignKeyConstraint(['user_id'], ['users.id'], onupdate='CASCADE', ondelete='CASCADE'), sa.PrimaryKeyConstraint('id')) op.create_index(op.f('ix_user_resources_created_at'), 'user_resources', ['created_at'], unique=False) op.create_index(op.f('ix_user_resources_type'), 'user_resources', ['type'], unique=False) op.create_index(op.f('ix_user_resources_updated_at'), 'user_resources', ['updated_at'], unique=False) op.create_table( 'user_resource_fulfillment', sa.Column('created_at', sau.ArrowType(), nullable=False), sa.Column('updated_at', sau.ArrowType(), nullable=False), sa.Column('id', sa.BigInteger(), nullable=False), sa.Column('fulfilling_resource_id', sa.BigInteger(), nullable=False), sa.Column('fulfilled_resource_id', sa.BigInteger(), nullable=False), sa.Column('fulfilled_quantity', sa.BigInteger(), nullable=False), sa.Column('confirmed_by_recipient', sa.Boolean(), server_default='0', nullable=False), sa.ForeignKeyConstraint(['fulfilled_resource_id'], ['user_resources.id'], onupdate='CASCADE', ondelete='RESTRICT'), sa.ForeignKeyConstraint(['fulfilling_resource_id'], ['user_resources.id'], onupdate='CASCADE', ondelete='RESTRICT'), sa.PrimaryKeyConstraint('id')) op.create_index(op.f('ix_user_resource_fulfillment_created_at'), 'user_resource_fulfillment', ['created_at'], unique=False) op.create_index(op.f('ix_user_resource_fulfillment_updated_at'), 'user_resource_fulfillment', ['updated_at'], unique=False)