-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use Flask custom CLI commands for custom scripts #138
Changes from all commits
c422aa6
45b108a
54d0b33
f2b7cd5
56d2afc
6fefac1
c9630b6
6d1d7df
bb64fa3
a373ccb
941cb06
42b5d49
cc9654b
1e365e1
95be2d7
6d65a04
75ca748
716128f
78da5d2
dfe2dd3
11096e8
6e177cd
6aecce5
7053d91
662ac67
6daef3e
020c4cf
f1a29eb
1459046
badb082
4cc0af4
69f3848
0dc857f
45b9e3f
e55bd99
5622433
aeff01a
55c2339
23a1a75
ddc6313
b83213b
6fc18d1
7e3cfc8
1a115af
00be3be
2c01c76
83ccce0
cd39d03
81868e9
873939c
1e2788b
0a837a8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,19 @@ else | |
PY_RUN_CMD := docker-compose run $(DOCKER_EXEC_ARGS) --rm $(APP_NAME) poetry run | ||
endif | ||
|
||
FLASK_CMD := $(PY_RUN_CMD) flask --env-file local.env | ||
|
||
################################################## | ||
# Local Development Environment Setup | ||
################################################## | ||
|
||
setup-local: | ||
# Configure poetry to use virtualenvs in the project directory | ||
poetry config virtualenvs.in-project true | ||
|
||
# Install dependencies | ||
poetry install --no-root | ||
|
||
################################################## | ||
# API Build & Run | ||
################################################## | ||
|
@@ -46,7 +59,6 @@ start: | |
run-logs: start | ||
docker-compose logs --follow --no-color $(APP_NAME) | ||
|
||
|
||
init: build init-db | ||
|
||
clean-volumes: ## Remove project docker volumes (which includes the DB state) | ||
|
@@ -57,13 +69,6 @@ stop: | |
|
||
check: format-check lint test | ||
|
||
# Set init-db as pre-requisite since there seems to be a race condition | ||
# where the DB can't yet receive connections if it's starting from a | ||
# clean state (e.g. after make stop, make clean-volumes, make openapi-spec) | ||
openapi-spec: init-db ## Generate OpenAPI spec | ||
$(PY_RUN_CMD) flask spec --format yaml --output ./openapi.yml | ||
|
||
|
||
################################################## | ||
# DB & migrations | ||
################################################## | ||
|
@@ -168,11 +173,21 @@ lint-security: # https://bandit.readthedocs.io/en/latest/index.html | |
|
||
|
||
################################################## | ||
# Scripts | ||
# CLI Commands | ||
################################################## | ||
|
||
create-user-csv: | ||
$(PY_RUN_CMD) create-user-csv | ||
cmd: ## Run Flask app CLI command (Run `make cli args="--help"` to see list of CLI commands) | ||
$(FLASK_CMD) $(args) | ||
|
||
cmd-user-create-csv: ## Create a CSV of the useres in the database (Run `make cli-user-create-csv args="--help"` to see the command's options) | ||
$(FLASK_CMD) user create-csv $(args) | ||
|
||
# Set init-db as pre-requisite since there seems to be a race condition | ||
# where the DB can't yet receive connections if it's starting from a | ||
# clean state (e.g. after make stop, make clean-volumes, make openapi-spec) | ||
openapi-spec: init-db ## Generate OpenAPI spec | ||
$(FLASK_CMD) spec --format yaml --output ./openapi.yml | ||
Comment on lines
+185
to
+189
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had to deal with that race condition on NJ as the Oracle DB takes 60+ seconds to startup: https://github.com/navapbc/archive-nj-dol-ui-claimant-api/blob/main/wait-for-local-oracle.sh - it just checks if a particular log message appears every 5 seconds. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh interesting! I wonder if there's a better way to do that here as well. |
||
|
||
|
||
################################################## | ||
# Miscellaneous Utilities | ||
|
@@ -184,10 +199,3 @@ login: start ## Start shell in running container | |
# Pauses for 5 seconds | ||
sleep-5: | ||
sleep 5 | ||
|
||
setup-local: | ||
# Configure poetry to use virtualenvs in the project directory | ||
poetry config virtualenvs.in-project true | ||
|
||
# Install dependencies | ||
poetry install --no-root |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from api.api.users.user_blueprint import user_blueprint | ||
|
||
# import user_commands module to register the CLI commands on the user_blueprint | ||
import api.api.users.user_commands # noqa: F401 E402 isort:skip | ||
|
||
# import user_commands module to register the API routes on the user_blueprint | ||
import api.api.users.user_routes # noqa: F401 E402 isort:skip | ||
|
||
|
||
__all__ = ["user_blueprint"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from apiflask import APIBlueprint | ||
|
||
user_blueprint = APIBlueprint("user", __name__, tag="User", cli_group="user") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import logging | ||
import os.path as path | ||
from typing import Optional | ||
|
||
import click | ||
|
||
import api.adapters.db as db | ||
import api.adapters.db.flask_db as flask_db | ||
import api.services.users as user_service | ||
from api.api.users.user_blueprint import user_blueprint | ||
from api.util.datetime_util import utcnow | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
user_blueprint.cli.help = "User commands" | ||
|
||
|
||
@user_blueprint.cli.command("create-csv", help="Create a CSV of all users and their roles") | ||
@flask_db.with_db_session | ||
@click.option( | ||
"--dir", | ||
default=".", | ||
help="Directory to save output file in. Can be an S3 path (e.g. 's3://bucketname/folder/') Defaults to current directory ('.').", | ||
) | ||
@click.option( | ||
"--filename", | ||
default=None, | ||
help="Filename to save output file as. Defaults to '[timestamp]-user-roles.csv.", | ||
) | ||
def create_csv(db_session: db.Session, dir: str, filename: Optional[str]) -> None: | ||
if filename is None: | ||
filename = utcnow().strftime("%Y-%m-%d-%H-%M-%S") + "-user-roles.csv" | ||
filepath = path.join(dir, filename) | ||
user_service.create_user_csv(db_session, filepath) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
"""cascade on delete | ||
|
||
Revision ID: 9fe657340f70 | ||
Revises: 4ff1160282d1 | ||
Create Date: 2023-02-21 18:16:56.052679 | ||
|
||
""" | ||
from alembic import op | ||
|
||
# revision identifiers, used by Alembic. | ||
revision = "9fe657340f70" | ||
down_revision = "4ff1160282d1" | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade(): | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
op.drop_constraint("role_user_id_user_fkey", "role", type_="foreignkey") | ||
op.create_foreign_key( | ||
op.f("role_user_id_user_fkey"), "role", "user", ["user_id"], ["id"], ondelete="CASCADE" | ||
) | ||
# ### end Alembic commands ### | ||
|
||
|
||
def downgrade(): | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
op.drop_constraint(op.f("role_user_id_user_fkey"), "role", type_="foreignkey") | ||
op.create_foreign_key("role_user_id_user_fkey", "role", "user", ["user_id"], ["id"]) | ||
# ### end Alembic commands ### |
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would we run commands non-locally?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ECS could run it directly with via
poetry run flask --app api.app <cmd>
.Open to suggestions though. The challenge I ran into with the Makefile is that while docker-compose.yml has
env_file: local.env
which automatically loads the env file, running it on local host machine withPY_RUN_APPROACH=local
won't automatically load the env vars.I would love to move away from the
load_local_env_vars
function in our code. I think it's not very elegant to haveif environment == <x>
checks in the application code itself. I was actually a bit confused to see that load_local_env_vars was being called in production, and only realized upon digging into the function that it is a no-op based on the ENVIRONMENT env var.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with moving the env var loading somewhere else.
I think the issue I had here was that we can't use
FLASK_CMD
anywhere non-locally as the env-file is in the command itself. Would it make more sense to do some sort ofif
statement in the makefile to add that bit to the command if you're running locally? That way when running non-locally it doesn't get used.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that makes sense. How do I detect if Makefile is running locally? I'm caught up in a bit of chicken-egg. The
ENVIRONMENT=local
setting is defined inlocal.env
. Should we make that specific environment variable something that is defined outside oflocal.env
, either withdirenv
or something?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something in the setup-local command?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm yeah maybe. Anyways I created a ticket to revisit env vars more thoroughly #136