From 21a3956d095be5b628a1b2b31e5c66025ec21808 Mon Sep 17 00:00:00 2001 From: Maya Treacy Date: Sun, 31 May 2020 10:03:17 +1000 Subject: [PATCH 1/8] MS Backend server for BIT development purpose replace db uri add Flask-Cors to requirements.txt linting with black formatter remove fetch env variables duplication change pull-push branch for github action to bit branch add postgresql test db add shell_context_processor Add -h postgres to psql command Place PGPASSWORD at the start of psql command Add env for running test * Update main.yml (Patch #21) Co-authored-by: Aditya Kurkure use non-macOS syntax for db_uri and add db envs Add postgres db url for github action Add test for db_test_uri remove hard coded test db uri Add psycopg2 Fix db type to postgres+psycopg2 add env to Generate coverage report move env to global runner focus pytest cov on tests folder Remove print command --- .github/workflows/main.yml | 43 ++++++++++++++++--- app/api/dao/user.py | 8 ++-- app/api/models/admin.py | 4 +- app/api/models/user.py | 12 ++++-- app/api/resources/admin.py | 2 +- app/api/resources/user.py | 9 ++-- app/api/validations/user.py | 8 ++-- app/database/models/mentorship_relation.py | 16 +++---- app/database/models/task_comment.py | 8 ++-- app/database/models/user.py | 4 +- config.py | 35 +++++++++------ requirements.txt | 1 + run.py | 38 +++++++++++++++- tests/test_app_config.py | 20 ++++++--- tests/users/test_dao_update_user.py | 16 +++---- ...est_validation_update_user_request_data.py | 4 +- 16 files changed, 160 insertions(+), 68 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2589843ca..eae28425a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,33 +5,66 @@ name: Run tests on: push: - branches: [ develop ] + branches: [ bit ] pull_request: - branches: [ develop ] + branches: [ bit ] jobs: build: runs-on: ubuntu-latest - + env: + DB_TYPE: postgresql+psycopg2 + DB_USERNAME: postgres + DB_PASSWORD: postgres + DB_ENDPOINT: localhost:5432 + DB_TEST_NAME: bit_schema_test + services: + postgres: + image: postgres + env: + POSTGRES_PASSWORD: postgres + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 steps: - uses: actions/checkout@v2 + - name: Connect to PostgreSQL + run: | + PGPASSWORD=postgres psql -h localhost -c 'CREATE DATABASE bit_schema_test;' -U postgres + PGPASSWORD=postgres psql -h localhost -c 'CREATE SCHEMA bitschema;' -U postgres -d bit_schema_test + PGPASSWORD=postgres psql -h localhost -c 'CREATE SCHEMA test_schema;' -U postgres -d bit_schema_test + PGPASSWORD=postgres psql -h localhost -c 'create SCHEMA test_schema_2;' -U postgres -d bit_schema_test + PGPASSWORD=postgres psql -h localhost -c '\dn;' -U postgres -d bit_schema_test + PGPASSWORD=postgres psql -h localhost -c 'show search_path;' -U postgres -d bit_schema_test + PGPASSWORD=postgres psql -h localhost -c "ALTER DATABASE bit_schema_test SET search_path TO bitschema,public;" -U postgres -d bit_schema_test + PGPASSWORD=postgres psql -h localhost -c 'show search_path;' -U postgres -d bit_schema_test + env: + POSTGRES_HOST: localhost + POSTGRES_PORT: 5432 - name: Set up Python 3.6 uses: actions/setup-python@v2 with: python-version: 3.6 - name: Install dependencies run: | - python -m pip install --upgrade pip + sudo -H python -m pip install --upgrade pip + pip --version if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Run tests run: | python -m unittest discover tests -v + - name: Generate coverage report run: | pip install pytest pip install pytest-cov - pytest --cov=./ --cov-report=xml + pytest --cov tests/ --cov-report=xml + - name: Upload coverage to Codecov uses: codecov/codecov-action@v1 with: diff --git a/app/api/dao/user.py b/app/api/dao/user.py index fe387e01a..ce7296cb5 100644 --- a/app/api/dao/user.py +++ b/app/api/dao/user.py @@ -259,11 +259,11 @@ def update_user_profile(user_id: int, data: Dict[str, str]): else: user.occupation = None - if "organization" in data: - if data["organization"]: - user.organization = data["organization"] + if "current_organization" in data: + if data["current_organization"]: + user.current_organization = data["current_organization"] else: - user.organization = None + user.current_organization = None if "slack_username" in data: if data["slack_username"]: diff --git a/app/api/models/admin.py b/app/api/models/admin.py index a420a2293..4cc07887f 100644 --- a/app/api/models/admin.py +++ b/app/api/models/admin.py @@ -32,7 +32,9 @@ def add_models_to_namespace(api_namespace): "bio": fields.String(required=True, description="User bio"), "location": fields.String(required=True, description="User location"), "occupation": fields.String(required=True, description="User occupation"), - "organization": fields.String(required=True, description="User organization"), + "current_organization": fields.String( + required=True, description="User current organization" + ), "skills": fields.String(required=True, description="User skills"), }, ) diff --git a/app/api/models/user.py b/app/api/models/user.py index 0e64af608..7baaa90c7 100644 --- a/app/api/models/user.py +++ b/app/api/models/user.py @@ -47,7 +47,9 @@ def add_models_to_namespace(api_namespace): "bio": fields.String(required=True, description="User bio"), "location": fields.String(required=True, description="User location"), "occupation": fields.String(required=True, description="User occupation"), - "organization": fields.String(required=True, description="User organization"), + "current_organization": fields.String( + required=True, description="User current_organization" + ), "interests": fields.String(required=True, description="User interests"), "skills": fields.String(required=True, description="User skills"), "need_mentoring": fields.Boolean( @@ -91,7 +93,9 @@ def add_models_to_namespace(api_namespace): "bio": fields.String(required=False, description="User bio"), "location": fields.String(required=False, description="User location"), "occupation": fields.String(required=False, description="User occupation"), - "organization": fields.String(required=False, description="User organization"), + "current_organization": fields.String( + required=False, description="User current_organization" + ), "slack_username": fields.String( required=False, description="User slack username" ), @@ -179,7 +183,9 @@ def add_models_to_namespace(api_namespace): "bio": fields.String(required=False, description="User bio"), "location": fields.String(required=False, description="User location"), "occupation": fields.String(required=False, description="User occupation"), - "organization": fields.String(required=False, description="User organization"), + "current_organization": fields.String( + required=False, description="User current_organization" + ), "slack_username": fields.String( required=False, description="User slack username" ), diff --git a/app/api/resources/admin.py b/app/api/resources/admin.py index b406d1d5d..de02d46d7 100644 --- a/app/api/resources/admin.py +++ b/app/api/resources/admin.py @@ -98,7 +98,7 @@ def get(cls): A admin user with valid access token can view the list of all admins. The endpoint doesn't take any other input. A JSON array having an object for each admin user is returned. The array contains id, username, name, slack_username, bio, - location, occupation, organization, skills. + location, occupation, current_organization, skills. The current admin user's details are not returned. """ user_id = get_jwt_identity() diff --git a/app/api/resources/user.py b/app/api/resources/user.py index a1d463cb9..fad0e67ab 100644 --- a/app/api/resources/user.py +++ b/app/api/resources/user.py @@ -63,8 +63,8 @@ def get(cls): A user with valid access token can view the list of users. The endpoint doesn't take any other input. A JSON array having an object for each user is returned. The array contains id, username, name, slack_username, bio, - location, occupation, organization, interests, skills, need_mentoring, - available_to_mentor, registration_date. The current user's details are not returned. + location, occupation, current_organization, interests, skills, need_mentoring, + available_to_mentor. The current user's details are not returned. """ page = request.args.get("page", default=UserDAO.DEFAULT_PAGE, type=int) @@ -158,7 +158,7 @@ def put(cls): A user with valid access token can use this endpoint to edit his/her own user details. The endpoint takes any of the given parameters (name, username, - bio, location, occupation, organization, slack_username, social_media_links, + bio, location, occupation, current_organization, slack_username, social_media_links, skills, interests, resume_url, photo_url, need_mentoring, available_to_mentor). The response contains a success message. """ @@ -269,7 +269,7 @@ def get(cls): A user with valid access token can view the list of verified users. The endpoint doesn't take any other input. A JSON array having an object for each user is returned. The array contains id, username, name, slack_username, bio, - location, occupation, organization, interests, skills, need_mentoring, + location, occupation, current_organization, interests, skills, need_mentoring, available_to_mentor. The current user's details are not returned. """ @@ -337,7 +337,6 @@ def post(cls): if result[1] is HTTPStatus.CREATED: send_email_verification_message(data["name"], data["email"]) - return result diff --git a/app/api/validations/user.py b/app/api/validations/user.py index a88ee6ead..fd2d77dd8 100644 --- a/app/api/validations/user.py +++ b/app/api/validations/user.py @@ -162,13 +162,13 @@ def validate_update_profile_request_data(data): if not is_valid[0]: return is_valid[1] - organization = data.get("organization", None) - if organization: + current_organization = data.get("current_organization", None) + if current_organization: is_valid = validate_length( - len(get_stripped_string(organization)), + len(get_stripped_string(current_organization)), 0, ORGANIZATION_MAX_LENGTH, - "organization", + "current_organization", ) if not is_valid[0]: return is_valid[1] diff --git a/app/database/models/mentorship_relation.py b/app/database/models/mentorship_relation.py index d3d4be6cc..a6fcfb89c 100644 --- a/app/database/models/mentorship_relation.py +++ b/app/database/models/mentorship_relation.py @@ -16,10 +16,10 @@ class MentorshipRelationModel(db.Model): action_user_id: integer indicates id of action user. mentor: relationship between UserModel and mentorship_relation. mentee: relationship between UserModel and mentorship_relation. - creation_date: float that defines the date of creation of the mentorship. - accept_date: float that indicates the date of acceptance of mentorship. - start_date: float that indicates the starting date of mentorship. - end_date: float that indicates the ending date of mentorship. + creation_date: numeric that defines the date of creation of the mentorship. + accept_date: numeric that indicates the date of acceptance of mentorship. + start_date: numeric that indicates the starting date of mentorship. + end_date: numeric that indicates the ending date of mentorship. state: enumeration that indicates state of mentorship. notes: string that indicates any notes. tasks_list_id: integer indicates the id of the tasks_list @@ -47,10 +47,10 @@ class MentorshipRelationModel(db.Model): primaryjoin="MentorshipRelationModel.mentee_id == UserModel.id", ) - creation_date = db.Column(db.Float, nullable=False) - accept_date = db.Column(db.Float) - start_date = db.Column(db.Float) - end_date = db.Column(db.Float) + creation_date = db.Column(db.Numeric("16,6", asdecimal=False), nullable=False) + accept_date = db.Column(db.Numeric("16,6", asdecimal=False)) + start_date = db.Column(db.Numeric("16,6", asdecimal=False)) + end_date = db.Column(db.Numeric("16,6", asdecimal=False)) state = db.Column(db.Enum(MentorshipRelationState), nullable=False) notes = db.Column(db.String(400)) diff --git a/app/database/models/task_comment.py b/app/database/models/task_comment.py index d2f532496..c4445da0f 100644 --- a/app/database/models/task_comment.py +++ b/app/database/models/task_comment.py @@ -11,8 +11,8 @@ class TaskCommentModel(db.Model): task_id: An integer for storing the task's id. user_id: An integer for storing the user's id. relation_id: An integer for storing the relation's id. - creation_date: A float indicating comment's creation date. - modification_date: A float indicating the modification date. + creation_date: A numeric indicating comment's creation date. + modification_date: A numeric indicating the modification date. comment: A string indicating the comment. """ @@ -24,8 +24,8 @@ class TaskCommentModel(db.Model): user_id = db.Column(db.Integer, db.ForeignKey("users.id")) task_id = db.Column(db.Integer, db.ForeignKey("tasks_list.id")) relation_id = db.Column(db.Integer, db.ForeignKey("mentorship_relations.id")) - creation_date = db.Column(db.Float, nullable=False) - modification_date = db.Column(db.Float) + creation_date = db.Column(db.Numeric("16,6", asdecimal=False), nullable=False) + modification_date = db.Column(db.Numeric("16,6", asdecimal=False)) comment = db.Column(db.String(COMMENT_MAX_LENGTH), nullable=False) def __init__(self, user_id, task_id, relation_id, comment): diff --git a/app/database/models/user.py b/app/database/models/user.py index 943ef0d21..02f250ff4 100644 --- a/app/database/models/user.py +++ b/app/database/models/user.py @@ -46,7 +46,7 @@ class UserModel(db.Model): bio = db.Column(db.String(500)) location = db.Column(db.String(80)) occupation = db.Column(db.String(80)) - organization = db.Column(db.String(80)) + current_organization = db.Column(db.String(80)) slack_username = db.Column(db.String(80)) social_media_links = db.Column(db.String(500)) skills = db.Column(db.String(500)) @@ -97,7 +97,7 @@ def json(self): "bio": self.bio, "location": self.location, "occupation": self.occupation, - "organization": self.organization, + "current_organization": self.current_organization, "slack_username": self.slack_username, "social_media_links": self.social_media_links, "skills": self.skills, diff --git a/config.py b/config.py index 5d655f9de..ae79ba0a8 100644 --- a/config.py +++ b/config.py @@ -42,6 +42,7 @@ class BaseConfig(object): DB_PASSWORD = os.getenv("DB_PASSWORD") DB_ENDPOINT = os.getenv("DB_ENDPOINT") DB_NAME = os.getenv("DB_NAME") + DB_TEST_NAME = os.getenv("DB_TEST_NAME") UNVERIFIED_USER_THRESHOLD = 2592000 # 30 days @@ -84,15 +85,17 @@ def build_db_uri( db_endpoint_arg=DB_ENDPOINT, db_name_arg=DB_NAME, ): - """Build remote database uri using specific environment variables.""" - - return "{db_type}://{db_user}:{db_password}@{db_endpoint}/{db_name}".format( - db_type=db_type_arg, - db_user=db_user_arg, - db_password=db_password_arg, - db_endpoint=db_endpoint_arg, - db_name=db_name_arg, - ) + return f"{db_type_arg}://{db_user_arg}:{db_password_arg}@{db_endpoint_arg}/{db_name_arg}" + + @staticmethod + def build_db_test_uri( + db_type_arg=DB_TYPE, + db_user_arg=DB_USERNAME, + db_password_arg=DB_PASSWORD, + db_endpoint_arg=DB_ENDPOINT, + db_name_arg=DB_TEST_NAME, + ): + return f"{db_type_arg}://{db_user_arg}:{db_password_arg}@{db_endpoint_arg}/{db_name_arg}" class ProductionConfig(BaseConfig): @@ -122,8 +125,11 @@ class LocalConfig(BaseConfig): DEBUG = True - # Using a local sqlite database - SQLALCHEMY_DATABASE_URI = "sqlite:///local_data.db" + # Using a local postgre databases on MacOS + SQLALCHEMY_DATABASE_URI = "postgresql:///bit_schema" + + # Using a local postgre databases on other OS + # SQLALCHEMY_DATABASE_URI = BaseConfig.build_db_uri() class TestingConfig(BaseConfig): @@ -132,8 +138,11 @@ class TestingConfig(BaseConfig): TESTING = True MOCK_EMAIL = True - # Use in-memory SQLite database for testing - SQLALCHEMY_DATABASE_URI = "sqlite://" + # Using a local postgre database on MacOS + # SQLALCHEMY_DATABASE_URI = "postgresql:///bit_schema_test" + + # Using a local postgre database on other OS + SQLALCHEMY_DATABASE_URI = BaseConfig.build_db_test_uri() def get_env_config() -> str: diff --git a/requirements.txt b/requirements.txt index e994c9c3b..1d0862ed7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ APScheduler==3.6.3 coverage==5.3 Flask==1.0.2 +Flask-Cors==3.0.9 Flask-JWT-Extended==3.25.0 Flask-Mail==0.9.1 Flask-Migrate==2.5.3 diff --git a/run.py b/run.py index 6f7ab83fe..86ec9b71f 100644 --- a/run.py +++ b/run.py @@ -1,6 +1,9 @@ from flask import Flask from config import get_env_config from flask_migrate import Migrate +from flask_cors import CORS + +cors = CORS() def create_app(config_filename: str) -> Flask: @@ -14,8 +17,17 @@ def create_app(config_filename: str) -> Flask: db.init_app(app) + from app.database.models.user import UserModel + from app.database.models.mentorship_relation import ( + MentorshipRelationModel, + ) + from app.database.models.tasks_list import TasksListModel + from app.database.models.task_comment import TaskCommentModel + migrate = Migrate(app, db) + cors.init_app(app, resources={r"*": {"origins": "http:localhost:5000"}}) + from app.api.jwt_extension import jwt jwt.init_app(app) @@ -40,10 +52,34 @@ def create_app(config_filename: str) -> Flask: @application.before_first_request def create_tables(): + from app.database.sqlalchemy_extension import db + from app.database.models.user import UserModel + from app.database.models.mentorship_relation import ( + MentorshipRelationModel, + ) + from app.database.models.tasks_list import TasksListModel + from app.database.models.task_comment import TaskCommentModel + db.create_all() +@application.shell_context_processor +def make_shell_context(): + return { + "db": db, + "UserModel": UserModel, + "MentorshipRelationModel": MentorshipRelationModel, + "TaskListModel": TasksListModel, + "TaskCommentModel": TaskCommentModel, + "OrganizationModel": OrganizationModel, + "ProgramModel": ProgramModel, + "UserExtensionModel": UserExtensionModel, + "PersonalBackgroundModel": PersonalBackgroundModel, + "MentorshipRelationExtensionModel": MentorshipRelationExtensionModel, + } + + if __name__ == "__main__": - application.run(port=5000) + application.run(port=4000) diff --git a/tests/test_app_config.py b/tests/test_app_config.py index 6f33475d0..2f8c2f029 100644 --- a/tests/test_app_config.py +++ b/tests/test_app_config.py @@ -24,7 +24,6 @@ def test_app_testing_config(self): self.assertFalse(application.config["DEBUG"]) self.assertTrue(application.config["TESTING"]) self.assertFalse(application.config["SQLALCHEMY_TRACK_MODIFICATIONS"]) - self.assertEqual("sqlite://", application.config["SQLALCHEMY_DATABASE_URI"]) self.assertIsNotNone(current_app) # testing JWT configurations @@ -35,7 +34,7 @@ def test_app_testing_config(self): timedelta(weeks=4), application.config["JWT_REFRESH_TOKEN_EXPIRES"] ) - def test_get_bd_uri_function(self): + def test_get_db_uri_function(self): expected_result = "db_type_example://db_user_example:db_password_example@db_endpoint_example/db_name_example" actual_result = BaseConfig.build_db_uri( @@ -47,6 +46,18 @@ def test_get_bd_uri_function(self): ) self.assertEqual(expected_result, actual_result) + def test_get_db__test_uri_function(self): + + expected_result = "db_type_example://db_user_example:db_password_example@db_endpoint_example/db_test_name_example" + actual_result = BaseConfig.build_db_test_uri( + db_type_arg="db_type_example", + db_user_arg="db_user_example", + db_password_arg="db_password_example", + db_endpoint_arg="db_endpoint_example", + db_name_arg="db_test_name_example", + ) + self.assertEqual(expected_result, actual_result) + class TestDevelopmentConfig(TestCase): def create_app(self): @@ -89,7 +100,6 @@ def test_app_development_config(self): self.assertTrue(application.config["DEBUG"]) self.assertFalse(application.config["TESTING"]) self.assertFalse(application.config["SQLALCHEMY_TRACK_MODIFICATIONS"]) - # self.assertEqual('mysql_something', application.config['SQLALCHEMY_DATABASE_URI']) self.assertIsNotNone(current_app) # testing JWT configurations @@ -113,9 +123,6 @@ def test_app_development_config(self): self.assertTrue(application.config["DEBUG"]) self.assertFalse(application.config["TESTING"]) self.assertFalse(application.config["SQLALCHEMY_TRACK_MODIFICATIONS"]) - self.assertEqual( - "sqlite:///local_data.db", application.config["SQLALCHEMY_DATABASE_URI"] - ) self.assertIsNotNone(current_app) # testing JWT configurations @@ -143,7 +150,6 @@ def test_app_production_config(self): self.assertFalse(application.config["DEBUG"]) self.assertFalse(application.config["TESTING"]) self.assertFalse(application.config["SQLALCHEMY_TRACK_MODIFICATIONS"]) - # self.assertEqual('mysql_something', application.config['SQLALCHEMY_DATABASE_URI']) self.assertIsNotNone(current_app) # testing JWT configurations diff --git a/tests/users/test_dao_update_user.py b/tests/users/test_dao_update_user.py index c9fd422e3..abcbe8444 100644 --- a/tests/users/test_dao_update_user.py +++ b/tests/users/test_dao_update_user.py @@ -8,30 +8,30 @@ class TestUpdateUserDao(BaseTestCase): def test_dao_update_user(self): self.assertIsNone(self.admin_user.occupation) - self.assertIsNone(self.admin_user.organization) + self.assertIsNone(self.admin_user.current_organization) - data = dict(occupation="good_developer", organization="good_org") + data = dict(occupation="good_developer", current_organization="good_org") UserDAO.update_user_profile(self.admin_user.id, data) self.assertEqual("good_developer", self.admin_user.occupation) - self.assertEqual("good_org", self.admin_user.organization) + self.assertEqual("good_org", self.admin_user.current_organization) def test_update_fields_with_empty_data(self): self.assertIsNone(self.admin_user.occupation) - self.assertIsNone(self.admin_user.organization) + self.assertIsNone(self.admin_user.current_organization) - data = dict(occupation="good_developer", organization="good_org") + data = dict(occupation="good_developer", current_organization="good_org") UserDAO.update_user_profile(self.admin_user.id, data) self.assertEqual("good_developer", self.admin_user.occupation) - self.assertEqual("good_org", self.admin_user.organization) + self.assertEqual("good_org", self.admin_user.current_organization) - data = dict(occupation="", organization="") + data = dict(occupation="", current_organization="") UserDAO.update_user_profile(self.admin_user.id, data) self.assertIsNone(self.admin_user.occupation) - self.assertIsNone(self.admin_user.organization) + self.assertIsNone(self.admin_user.current_organization) if __name__ == "__main__": diff --git a/tests/users/test_validation_update_user_request_data.py b/tests/users/test_validation_update_user_request_data.py index a0dd7211f..103fa3586 100644 --- a/tests/users/test_validation_update_user_request_data.py +++ b/tests/users/test_validation_update_user_request_data.py @@ -45,8 +45,8 @@ def test_update_user_organization_request_data_validation(self): secure_random.choice(ascii_lowercase) for x in range(ORGANIZATION_MAX_LENGTH + 1) ) - field_name = "organization" - request_body = dict(organization=random_generated_organization) + field_name = "current_organization" + request_body = dict(current_organization=random_generated_organization) expected_result = { "message": get_length_validation_error_message( From d897e7304e3448f67cc1e90026da241b3b22c815 Mon Sep 17 00:00:00 2001 From: epicadk Date: Mon, 8 Mar 2021 12:19:44 +0530 Subject: [PATCH 2/8] Feat: Docker for setup --- config.py | 2 +- docker-compose.yml | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 docker-compose.yml diff --git a/config.py b/config.py index ae79ba0a8..9a80d0f12 100644 --- a/config.py +++ b/config.py @@ -126,7 +126,7 @@ class LocalConfig(BaseConfig): DEBUG = True # Using a local postgre databases on MacOS - SQLALCHEMY_DATABASE_URI = "postgresql:///bit_schema" + SQLALCHEMY_DATABASE_URI = "postgresql://postgres:postgres@postgres:5432/bit_schema" # Using a local postgre databases on other OS # SQLALCHEMY_DATABASE_URI = BaseConfig.build_db_uri() diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..9765fa968 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,22 @@ +services: + postgres: + image: postgres + environment: + POSTGRES_PASSWORD: postgres + #Default_DB that will be connected + POSTGRES_DB: bit_schema + restart: always + #options: + #--health-cmd pg_isready + #--health-interval 10s + #--health-timeout 5s + #--health-retries 5 + web: + build: . + ports: + - 4000:5000 + restart: always + + + + From 34dea0ddcecbe7e85a319a6cda770ec689a78b0e Mon Sep 17 00:00:00 2001 From: epicadk Date: Mon, 8 Mar 2021 12:23:46 +0530 Subject: [PATCH 3/8] Feat: Docker for setup(2) --- run.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/run.py b/run.py index 86ec9b71f..d0a668258 100644 --- a/run.py +++ b/run.py @@ -62,6 +62,10 @@ def create_tables(): from app.database.models.tasks_list import TasksListModel from app.database.models.task_comment import TaskCommentModel + db.session.execute("CREATE SCHEMA IF NOT EXISTS bit_schema") + db.session.execute("CREATE SCHEMA IF NOT EXISTS bit_schema_test") + db.session.execute("ALTER DATABASE bit_schema SET search_path TO bitschema,public;") + db.session.commit() db.create_all() From bba016817a1e6c28bd2cbd14616c0503def8ee52 Mon Sep 17 00:00:00 2001 From: epicadk Date: Mon, 8 Mar 2021 14:06:56 +0530 Subject: [PATCH 4/8] Feat: Docker for setup(3) --- Dockerfile | 6 ++++++ run.py | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7de5c3ab5..374be4b62 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,4 +3,10 @@ COPY ./requirements.txt /dockerBuild/requirements.txt WORKDIR /dockerBuild RUN pip install --no-cache-dir -r requirements.txt COPY . /dockerBuild +ENV DB_TYPE=postgresql +ENV DB_USERNAME=postgres +ENV DB_PASSWORD=postgres +ENV DB_ENDPOINT=postgres:5432 +ENV DB_NAME=bit_schema +ENV FLASK_APP=run.py CMD ["flask", "run", "--host", "0.0.0.0"] diff --git a/run.py b/run.py index d0a668258..ba5237e0c 100644 --- a/run.py +++ b/run.py @@ -86,4 +86,5 @@ def make_shell_context(): if __name__ == "__main__": - application.run(port=4000) + # if we use docker then we can also run it on the default 5000 port + application.run(port=5000) From 10bc0891398b549638804dcfd23fa9c64becabd2 Mon Sep 17 00:00:00 2001 From: epicadk Date: Mon, 8 Mar 2021 14:21:13 +0530 Subject: [PATCH 5/8] Feat: Docker for setup(4) --- run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.py b/run.py index ba5237e0c..c9d6f8839 100644 --- a/run.py +++ b/run.py @@ -26,7 +26,7 @@ def create_app(config_filename: str) -> Flask: migrate = Migrate(app, db) - cors.init_app(app, resources={r"*": {"origins": "http:localhost:5000"}}) + cors.init_app(app, resources={r"*": {"origins": "http:BIT:5000"}}) from app.api.jwt_extension import jwt From 1a52c3eac825507d34fbede55a6a23a5a9ed0d76 Mon Sep 17 00:00:00 2001 From: epicadk Date: Tue, 9 Mar 2021 13:59:25 +0530 Subject: [PATCH 6/8] Docker setup(3) --- Dockerfile | 1 + config.py | 7 +------ run.py | 11 ++++++++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index 374be4b62..ce352f641 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,7 @@ ENV DB_TYPE=postgresql ENV DB_USERNAME=postgres ENV DB_PASSWORD=postgres ENV DB_ENDPOINT=postgres:5432 +ENV DB_TEST_NAME=bit_schema_test ENV DB_NAME=bit_schema ENV FLASK_APP=run.py CMD ["flask", "run", "--host", "0.0.0.0"] diff --git a/config.py b/config.py index 9a80d0f12..cbae87f2b 100644 --- a/config.py +++ b/config.py @@ -124,12 +124,7 @@ class LocalConfig(BaseConfig): """Local configuration.""" DEBUG = True - - # Using a local postgre databases on MacOS - SQLALCHEMY_DATABASE_URI = "postgresql://postgres:postgres@postgres:5432/bit_schema" - - # Using a local postgre databases on other OS - # SQLALCHEMY_DATABASE_URI = BaseConfig.build_db_uri() + SQLALCHEMY_DATABASE_URI = BaseConfig.build_db_uri() class TestingConfig(BaseConfig): diff --git a/run.py b/run.py index c9d6f8839..bdbd3c465 100644 --- a/run.py +++ b/run.py @@ -12,9 +12,14 @@ def create_app(config_filename: str) -> Flask: # setup application environment app.config.from_object(config_filename) app.url_map.strict_slashes = False - from app.database.sqlalchemy_extension import db + print(app.config["SQLALCHEMY_DATABASE_URI"]) + if ( + app.config["SQLALCHEMY_DATABASE_URI"] + != "postgresql://postgres:postgres@postgres:5432/bit_schema" + ): + raise Exception(app.config["SQLALCHEMY_DATABASE_URI"]) db.init_app(app) from app.database.models.user import UserModel @@ -62,8 +67,8 @@ def create_tables(): from app.database.models.tasks_list import TasksListModel from app.database.models.task_comment import TaskCommentModel - db.session.execute("CREATE SCHEMA IF NOT EXISTS bit_schema") - db.session.execute("CREATE SCHEMA IF NOT EXISTS bit_schema_test") + db.session.execute("CREATE SCHEMA IF NOT EXISTS bitschema") + db.session.execute("CREATE SCHEMA IF NOT EXISTS bitschematest") db.session.execute("ALTER DATABASE bit_schema SET search_path TO bitschema,public;") db.session.commit() db.create_all() From 948ab2abc1b85d402aed38abde06b2f73b11ad70 Mon Sep 17 00:00:00 2001 From: epicadk Date: Tue, 9 Mar 2021 18:37:08 +0530 Subject: [PATCH 7/8] minor bug fix --- Dockerfile | 1 + config.py | 3 ++- docker-compose.yml | 9 +-------- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index ce352f641..8705b06a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,7 @@ ENV DB_TYPE=postgresql ENV DB_USERNAME=postgres ENV DB_PASSWORD=postgres ENV DB_ENDPOINT=postgres:5432 +ENV DB_TEST_ENDPOINT=test_postgres:5432 ENV DB_TEST_NAME=bit_schema_test ENV DB_NAME=bit_schema ENV FLASK_APP=run.py diff --git a/config.py b/config.py index cbae87f2b..dd1adee46 100644 --- a/config.py +++ b/config.py @@ -43,6 +43,7 @@ class BaseConfig(object): DB_ENDPOINT = os.getenv("DB_ENDPOINT") DB_NAME = os.getenv("DB_NAME") DB_TEST_NAME = os.getenv("DB_TEST_NAME") + DB_TEST_ENDPOINT = os.getenv("DB_TEST_ENDPOINT", DB_ENDPOINT) UNVERIFIED_USER_THRESHOLD = 2592000 # 30 days @@ -92,7 +93,7 @@ def build_db_test_uri( db_type_arg=DB_TYPE, db_user_arg=DB_USERNAME, db_password_arg=DB_PASSWORD, - db_endpoint_arg=DB_ENDPOINT, + db_endpoint_arg=DB_TEST_ENDPOINT, db_name_arg=DB_TEST_NAME, ): return f"{db_type_arg}://{db_user_arg}:{db_password_arg}@{db_endpoint_arg}/{db_name_arg}" diff --git a/docker-compose.yml b/docker-compose.yml index 9765fa968..27ba38444 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,17 +5,10 @@ services: POSTGRES_PASSWORD: postgres #Default_DB that will be connected POSTGRES_DB: bit_schema - restart: always - #options: - #--health-cmd pg_isready - #--health-interval 10s - #--health-timeout 5s - #--health-retries 5 web: build: . ports: - - 4000:5000 - restart: always + - 4000:5000 From ea5104957663a25911d9d11ca002149f9f3503d1 Mon Sep 17 00:00:00 2001 From: epicadk Date: Tue, 9 Mar 2021 19:04:50 +0530 Subject: [PATCH 8/8] minor bug fix(2) --- run.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/run.py b/run.py index bdbd3c465..a16d2925f 100644 --- a/run.py +++ b/run.py @@ -14,12 +14,6 @@ def create_app(config_filename: str) -> Flask: app.url_map.strict_slashes = False from app.database.sqlalchemy_extension import db - print(app.config["SQLALCHEMY_DATABASE_URI"]) - if ( - app.config["SQLALCHEMY_DATABASE_URI"] - != "postgresql://postgres:postgres@postgres:5432/bit_schema" - ): - raise Exception(app.config["SQLALCHEMY_DATABASE_URI"]) db.init_app(app) from app.database.models.user import UserModel @@ -67,10 +61,6 @@ def create_tables(): from app.database.models.tasks_list import TasksListModel from app.database.models.task_comment import TaskCommentModel - db.session.execute("CREATE SCHEMA IF NOT EXISTS bitschema") - db.session.execute("CREATE SCHEMA IF NOT EXISTS bitschematest") - db.session.execute("ALTER DATABASE bit_schema SET search_path TO bitschema,public;") - db.session.commit() db.create_all()