diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..47ef7c07 --- /dev/null +++ b/.flake8 @@ -0,0 +1,5 @@ +[flake8] +max-line-length = 88 +select = C,E,F,W,B,B9 +ignore = E203, E501, W503 +exclude = __init__.py diff --git a/script/format.sh b/script/format.sh new file mode 100644 index 00000000..10345f12 --- /dev/null +++ b/script/format.sh @@ -0,0 +1,26 @@ +#!/bin/sh -e +set -x + +autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place ../sld-api-backend/api_v1 --exclude=__init__.py +autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place ../sld-api-backend/config --exclude=__init__.py +autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place ../sld-api-backend/db --exclude=__init__.py +autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place ../sld-api-backend/crud --exclude=__init__.py +autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place ../sld-api-backend/core --exclude=__init__.py +autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place ../sld-api-backend/helpers --exclude=__init__.py +autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place ../sld-api-backend/schemas --exclude=__init__.py +autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place ../sld-api-backend/security --exclude=__init__.py +autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place ../sld-api-backend/tasks --exclude=__init__.py + +autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place ../sld-dashboard/ --exclude=__init__.py +autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place ../sld-remote-state --exclude=__init__.py +autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place ../sld-schedule --exclude=__init__.py + +black ../sld-api-backend/ +black ../sld-dashboard/ +black ../sld-remote-state +black ../sld-schedule + +isort ../sld-api-backend/ --skip=../sld-api-backend/env/ +isort ../sld-dashboard/ --skip=../sld-dashboard/env/ +isort ../sld-remote-state --skip=../sld-remote-state/env/ +isort ../sld-schedule --skip=../sld-schedule/env/ diff --git a/sld-api-backend/api_v1/api.py b/sld-api-backend/api_v1/api.py index e169007f..e07c9f90 100644 --- a/sld-api-backend/api_v1/api.py +++ b/sld-api-backend/api_v1/api.py @@ -1,22 +1,19 @@ +from api_v1.endpoints import (activity_logs, auth, aws, azure, deploy, gcp, + healthy, plan, schedule, stacks, tasks, users, + variables) from fastapi import APIRouter -from api_v1.endpoints import users, auth, stacks -from api_v1.endpoints import aws, azure, gcp -from api_v1.endpoints import deploy, tasks, variables, healthy -from api_v1.endpoints import activity_logs, plan, schedule - - api_router = APIRouter() api_router.include_router(users.router, prefix="/users", tags=["Users"]) -api_router.include_router(auth.router,prefix="/authenticate",tags=["AccessToken"]) -api_router.include_router(aws.router,prefix="/accounts/aws",tags=["Aws"]) -api_router.include_router(gcp.router,prefix="/accounts/gcp",tags=["Gcloud"]) -api_router.include_router(azure.router,prefix="/accounts/azure",tags=["Azure"]) +api_router.include_router(auth.router, prefix="/authenticate", tags=["AccessToken"]) +api_router.include_router(aws.router, prefix="/accounts/aws", tags=["Aws"]) +api_router.include_router(gcp.router, prefix="/accounts/gcp", tags=["Gcloud"]) +api_router.include_router(azure.router, prefix="/accounts/azure", tags=["Azure"]) api_router.include_router(stacks.router, prefix="/stacks", tags=["Stacks"]) api_router.include_router(plan.router, prefix="/plan", tags=["Plan"]) api_router.include_router(deploy.router, prefix="/deploy", tags=["Deploy"]) api_router.include_router(schedule.router, prefix="/schedule", tags=["Schedule"]) api_router.include_router(tasks.router, prefix="/tasks", tags=["Tasks"]) api_router.include_router(activity_logs.router, prefix="/activity", tags=["Logs"]) -api_router.include_router(variables.router,prefix="/variables",tags=["Variables"]) +api_router.include_router(variables.router, prefix="/variables", tags=["Variables"]) api_router.include_router(healthy.router, tags=["Healthy"]) diff --git a/sld-api-backend/api_v1/endpoints/activity_logs.py b/sld-api-backend/api_v1/endpoints/activity_logs.py index 13aec90a..612e5d1c 100644 --- a/sld-api-backend/api_v1/endpoints/activity_logs.py +++ b/sld-api-backend/api_v1/endpoints/activity_logs.py @@ -1,14 +1,13 @@ -from sqlalchemy.orm import Session +from crud import activityLogs as crud_activity +from crud import user as crud_users from fastapi import APIRouter, Depends, HTTPException - from schemas import schemas from security import deps -from crud import activityLogs as crud_activity -from crud import user as crud_users +from sqlalchemy.orm import Session -#from fastapi_limiter import FastAPILimiter -#from fastapi_limiter.depends import RateLimiter -#import aioredis +# from fastapi_limiter import FastAPILimiter +# from fastapi_limiter.depends import RateLimiter +# import aioredis router = APIRouter() @@ -20,34 +19,37 @@ @router.get("/id/{username}") async def get_activity_logs_by_username( - username: str, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + username: str, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): if not crud_users.is_superuser(db, current_user): raise HTTPException(status_code=403, detail="Not enough permissions") if not crud_users.is_master(db, current_user): squad = current_user.squad - return crud_activity.get_activity_by_username_squad(db=db, username=username, squad=squad) + return crud_activity.get_activity_by_username_squad( + db=db, username=username, squad=squad + ) return crud_activity.get_activity_by_username(db, username=username) -@ router.get("/all") +@router.get("/all") async def get_all_activity_logs( - current_user: schemas.User = Depends(deps.get_current_active_user), - skip: int = 0, - limit: int = 100, - db: Session = Depends(deps.get_db)): + current_user: schemas.User = Depends(deps.get_current_active_user), + skip: int = 0, + limit: int = 100, + db: Session = Depends(deps.get_db), +): if not crud_users.is_superuser(db, current_user): raise HTTPException(status_code=403, detail="Not enough permissions") try: if not crud_users.is_master(db, current_user): squad = current_user.squad result = crud_activity.get_all_activity_by_squad( - db=db, squad=squad, skip=skip, limit=limit) + db=db, squad=squad, skip=skip, limit=limit + ) return result result = crud_activity.get_all_activity(db=db, skip=skip, limit=limit) return result except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") diff --git a/sld-api-backend/api_v1/endpoints/auth.py b/sld-api-backend/api_v1/endpoints/auth.py index 5c25ca1f..98a0ecbc 100644 --- a/sld-api-backend/api_v1/endpoints/auth.py +++ b/sld-api-backend/api_v1/endpoints/auth.py @@ -1,21 +1,20 @@ from typing import Any -from sqlalchemy.orm import Session + from fastapi import APIRouter, Depends from fastapi.security import OAuth2PasswordRequestForm - from schemas import schemas from schemas.schemas import Token from security import deps from security.tokens import validate_user - +from sqlalchemy.orm import Session router = APIRouter() @router.post("/access-token", response_model=Token) def login_access_token( - user: OAuth2PasswordRequestForm = Depends(), - db: Session = Depends(deps.get_db)) -> Any: + user: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(deps.get_db) +) -> Any: """ OAuth2 compatible token login, get an access token for future requests """ @@ -24,8 +23,8 @@ def login_access_token( @router.post("/access-token-json", response_model=Token) def login_access_token_json( - user: schemas.UserAuthenticate, - db: Session = Depends(deps.get_db)) -> dict: + user: schemas.UserAuthenticate, db: Session = Depends(deps.get_db) +) -> dict: """ OAuth2 compatible token login, get an access token for future requests """ diff --git a/sld-api-backend/api_v1/endpoints/aws.py b/sld-api-backend/api_v1/endpoints/aws.py index 19cc1852..df346698 100644 --- a/sld-api-backend/api_v1/endpoints/aws.py +++ b/sld-api-backend/api_v1/endpoints/aws.py @@ -1,72 +1,74 @@ -from sqlalchemy.orm import Session -from fastapi import APIRouter, Depends, HTTPException, Response - -from schemas import schemas +from crud import activityLogs as crud_activity from crud import aws as crud_aws from crud import user as crud_users -from crud import activityLogs as crud_activity +from fastapi import APIRouter, Depends, HTTPException, Response +from schemas import schemas from security import deps - +from sqlalchemy.orm import Session router = APIRouter() @router.post("/", status_code=200) async def create_new_aws_profile( - aws: schemas.AwsAsumeProfile, - response: Response, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + aws: schemas.AwsAsumeProfile, + response: Response, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): # Check if the user has privileges if not crud_users.is_master(db, current_user): raise HTTPException(status_code=403, detail="Not enough permissions") if "string" in [aws.squad, aws.environment]: raise HTTPException( status_code=409, - detail="The squad or environment field must have a value that is not a string.") + detail="The squad or environment field must have a value that is not a string.", + ) db_aws_account = crud_aws.get_squad_aws_profile( - db=db, squad=aws.squad, environment=aws.environment) + db=db, squad=aws.squad, environment=aws.environment + ) if db_aws_account: - raise HTTPException( - status_code=409, - detail="Account already exists") + raise HTTPException(status_code=409, detail="Account already exists") try: result = crud_aws.create_aws_profile(db=db, aws=aws) crud_activity.create_activity_log( db=db, username=current_user.username, squad=current_user.squad, - action=f'Create AWS account {aws.squad} {aws.environment}' + action=f"Create AWS account {aws.squad} {aws.environment}", ) - return {"result": f'Create AWS account {aws.squad} {aws.environment}'} + return {"result": f"Create AWS account {aws.squad} {aws.environment}"} except Exception as err: raise HTTPException(status_code=400, detail=str(err)) @router.get("/") async def get_all_aws_accounts( - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): # Check if the user has privileges if not crud_users.is_master(db, current_user): - return crud_aws.get_squad_aws_profile(db=db, squad=current_user.squad, environment=None ) + return crud_aws.get_squad_aws_profile( + db=db, squad=current_user.squad, environment=None + ) return crud_aws.get_all_aws_profile(db=db) @router.delete("/{aws_account_id}") async def delete_aws_account_by_id( - aws_account_id: int, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + aws_account_id: int, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): if not crud_users.is_master(db, current_user): raise HTTPException(status_code=403, detail="Not enough permissions") - result = crud_aws.delete_aws_profile_by_id( - db=db, aws_profile_id=aws_account_id) + result = crud_aws.delete_aws_profile_by_id(db=db, aws_profile_id=aws_account_id) crud_activity.create_activity_log( db=db, username=current_user.username, squad=current_user.squad, - action=f'Delete AWS account {aws_account_id}' + action=f"Delete AWS account {aws_account_id}", ) return result diff --git a/sld-api-backend/api_v1/endpoints/azure.py b/sld-api-backend/api_v1/endpoints/azure.py index 7495bc23..92b12917 100644 --- a/sld-api-backend/api_v1/endpoints/azure.py +++ b/sld-api-backend/api_v1/endpoints/azure.py @@ -1,71 +1,75 @@ -from sqlalchemy.orm import Session -from fastapi import APIRouter, Depends, HTTPException, Response - -from schemas import schemas +from crud import activityLogs as crud_activity from crud import azure as crud_azure from crud import user as crud_users -from crud import activityLogs as crud_activity +from fastapi import APIRouter, Depends, HTTPException, Response +from schemas import schemas from security import deps - +from sqlalchemy.orm import Session router = APIRouter() @router.post("/", status_code=200) async def create_new_azure_profile( - azure: schemas.AzureBase, - response: Response, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + azure: schemas.AzureBase, + response: Response, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): if not crud_users.is_master(db, current_user): raise HTTPException(status_code=403, detail="Not enough permissions") if "string" in [azure.squad, azure.environment]: raise HTTPException( status_code=409, - detail="The squad or environment field must have a value that is not a string.") + detail="The squad or environment field must have a value that is not a string.", + ) db_azure_account = crud_azure.get_squad_azure_profile( - db=db, squad=azure.squad, environment=azure.environment) + db=db, squad=azure.squad, environment=azure.environment + ) if db_azure_account: - raise HTTPException( - status_code=409, - detail="Account already exists") + raise HTTPException(status_code=409, detail="Account already exists") try: result = crud_azure.create_azure_profile(db=db, azure=azure) crud_activity.create_activity_log( db=db, username=current_user.username, squad=current_user.squad, - action=f'Create Azure Account {azure.subscription_id}' + action=f"Create Azure Account {azure.subscription_id}", ) - return {"result": f'Create Azure account {azure.squad} {azure.environment}'} + return {"result": f"Create Azure account {azure.squad} {azure.environment}"} except Exception as err: raise HTTPException(status_code=400, detail=str(err)) @router.get("/") async def get_all_azure_accounts( - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): if not crud_users.is_master(db, current_user): - return crud_azure.get_squad_azure_profile(db=db, squad=current_user.squad, environment=None) + return crud_azure.get_squad_azure_profile( + db=db, squad=current_user.squad, environment=None + ) return crud_azure.get_all_azure_profile(db=db) @router.delete("/{azure_account_id}") async def delete_azure_account_by_id( - azure_account_id: int, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + azure_account_id: int, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): if not crud_users.is_master(db, current_user): raise HTTPException(status_code=403, detail="Not enough permissions") result = crud_azure.delete_azure_profile_by_id( - db=db, azure_profile_id=azure_account_id) + db=db, azure_profile_id=azure_account_id + ) crud_activity.create_activity_log( db=db, username=current_user.username, squad=current_user.squad, - action=f'Delete Azure account {azure_account_id}' + action=f"Delete Azure account {azure_account_id}", ) return result diff --git a/sld-api-backend/api_v1/endpoints/deploy.py b/sld-api-backend/api_v1/endpoints/deploy.py index 73f79969..211ba044 100644 --- a/sld-api-backend/api_v1/endpoints/deploy.py +++ b/sld-api-backend/api_v1/endpoints/deploy.py @@ -1,32 +1,30 @@ -from sqlalchemy.orm import Session -from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Response, status - -from schemas import schemas from crud import deploys as crud_deploys from crud import tasks as crud_tasks from crud import user as crud_users -from security import deps -from security import tokens -from helpers.get_data import check_deploy_state, check_cron_schedule -from helpers.get_data import check_deploy_exist, check_deploy_task_pending_state -from helpers.get_data import check_squad_user -from helpers.get_data import stack, deploy, deploy_squad -from helpers.push_task import async_deploy, async_destroy -from helpers.push_task import async_output, async_unlock -from helpers.push_task import async_schedule_delete, async_schedule_add -from helpers.push_task import async_show - +from fastapi import (APIRouter, BackgroundTasks, Depends, HTTPException, + Response, status) +from helpers.get_data import (check_cron_schedule, check_deploy_exist, + check_deploy_state, + check_deploy_task_pending_state, + check_squad_user, deploy, deploy_squad, stack) +from helpers.push_task import (async_deploy, async_destroy, async_output, + async_schedule_add, async_schedule_delete, + async_show, async_unlock) +from schemas import schemas +from security import deps, tokens +from sqlalchemy.orm import Session router = APIRouter() @router.post("/", status_code=202) async def deploy_infra_by_stack_name( - response: Response, - background_tasks: BackgroundTasks, - deploy: schemas.DeployCreate, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + response: Response, + background_tasks: BackgroundTasks, + deploy: schemas.DeployCreate, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): response.status_code = status.HTTP_202_ACCEPTED # Get squad from current user @@ -34,23 +32,24 @@ async def deploy_infra_by_stack_name( # Get squad from current user if not crud_users.is_master(db, current_user): current_squad = current_user.squad - if not check_squad_user(current_user.squad, [deploy.squad]): - raise HTTPException(status_code=403, detail=f"Not enough permissions in {squad}") + if not check_squad_user(current_squad, [deploy.squad]): + raise HTTPException( + status_code=403, detail=f"Not enough permissions in {squad}" + ) # Get credentials by providers supported secreto = tokens.check_prefix( - db, stack_name=deploy.stack_name, environment=deploy.environment, squad=squad) + db, stack_name=deploy.stack_name, environment=deploy.environment, squad=squad + ) # Get info from stack data stack_data = stack(db, stack_name=deploy.stack_name) - branch = stack_data.branch if deploy.stack_branch == "" or deploy.stack_branch == None else deploy.stack_branch + branch = ( + stack_data.branch + if deploy.stack_branch == "" or deploy.stack_branch == None + else deploy.stack_branch + ) git_repo = stack_data.git_repo tf_ver = stack_data.tf_version - check_deploy_exist( - db, - deploy.name, - squad, - deploy.environment, - deploy.stack_name - ) + check_deploy_exist(db, deploy.name, squad, deploy.environment, deploy.stack_name) check_deploy_task_pending_state(deploy.name, squad, deploy.environment) try: # check crontime @@ -58,47 +57,47 @@ async def deploy_infra_by_stack_name( check_cron_schedule(deploy.destroy_time) # push task Deploy to queue and return task_id pipeline_deploy = async_deploy( - git_repo, - deploy.name, - deploy.stack_name, - deploy.environment, - squad, - branch, - tf_ver, - deploy.variables, - secreto, - deploy.tfvar_file, - deploy.project_path) + git_repo, + deploy.name, + deploy.stack_name, + deploy.environment, + squad, + branch, + tf_ver, + deploy.variables, + secreto, + deploy.tfvar_file, + deploy.project_path, + ) # Push deploy task data db_deploy = crud_deploys.create_new_deploy( - db=db, - deploy=deploy, - stack_branch=branch, - task_id=pipeline_deploy, - action="Apply", - squad=squad, - user_id=current_user.id, - username=current_user.username) + db=db, + deploy=deploy, + stack_branch=branch, + task_id=pipeline_deploy, + action="Apply", + squad=squad, + user_id=current_user.id, + username=current_user.username, + ) # Push task data db_task = crud_tasks.create_task( - db=db, - task_id=pipeline_deploy, - task_name=f"{deploy.stack_name}-{squad}-{deploy.environment}-{deploy.name}", - user_id=current_user.id, - deploy_id=db_deploy.id, - username=current_user.username, - squad=squad, - action="Apply" - ) + db=db, + task_id=pipeline_deploy, + task_name=f"{deploy.stack_name}-{squad}-{deploy.environment}-{deploy.name}", + user_id=current_user.id, + deploy_id=db_deploy.id, + username=current_user.username, + squad=squad, + action="Apply", + ) return {"task": db_task} except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") finally: try: - result = async_schedule_delete(db_deploy.id, squad) + async_schedule_delete(db_deploy.id, squad) # Add schedule async_schedule_add(db_deploy.id, squad) except Exception as err: @@ -107,12 +106,13 @@ async def deploy_infra_by_stack_name( @router.patch("/{deploy_id}", status_code=202) async def update_deploy_by_id( - deploy_id: int, - background_tasks: BackgroundTasks, - deploy_update: schemas.DeployUpdate, - response: Response, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + deploy_id: int, + background_tasks: BackgroundTasks, + deploy_update: schemas.DeployUpdate, + response: Response, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): response.status_code = status.HTTP_202_ACCEPTED # Get info from deploy data @@ -120,16 +120,23 @@ async def update_deploy_by_id( squad = deploy_data.squad if not crud_users.is_master(db, current_user): if not check_squad_user(current_user.squad, [deploy_data.squad]): - raise HTTPException(status_code=403, detail=f"Not enough permissions in {squad}") + raise HTTPException( + status_code=403, detail=f"Not enough permissions in {squad}" + ) stack_name = deploy_data.stack_name environment = deploy_data.environment name = deploy_data.name # Get credentials by providers supported secreto = tokens.check_prefix( - db, stack_name=stack_name, environment=environment, squad=squad) + db, stack_name=stack_name, environment=environment, squad=squad + ) # Get info from stack data stack_data = stack(db, stack_name=stack_name) - branch = stack_data.branch if deploy_update.stack_branch == "" or deploy_update.stack_branch == None else deploy_update.stack_branch + branch = ( + stack_data.branch + if deploy_update.stack_branch == "" or deploy_update.stack_branch == None + else deploy_update.stack_branch + ) git_repo = stack_data.git_repo tf_ver = stack_data.tf_version @@ -144,59 +151,61 @@ async def update_deploy_by_id( raise ValueError("Deploy state running, cannot upgrade") # push task Deploy Update to queue and return task_id pipeline_deploy = async_deploy( - git_repo, - name, - stack_name, - environment, - squad, - branch, - tf_ver, - deploy_update.variables, - secreto, - deploy_update.tfvar_file, - deploy_update.project_path) + git_repo, + name, + stack_name, + environment, + squad, + branch, + tf_ver, + deploy_update.variables, + secreto, + deploy_update.tfvar_file, + deploy_update.project_path, + ) # Push deploy task data crud_deploys.update_deploy( - db=db, - deploy_id=deploy_id, - task_id=pipeline_deploy, - action="Update", - user_id=current_user.id, - tfvar_file=deploy_update.tfvar_file, - project_path=deploy_update.project_path, - stack_branch=branch, - variables=deploy_update.variables, - start_time=deploy_update.start_time, - destroy_time=deploy_update.destroy_time, - username=current_user.username) + db=db, + deploy_id=deploy_id, + task_id=pipeline_deploy, + action="Update", + user_id=current_user.id, + tfvar_file=deploy_update.tfvar_file, + project_path=deploy_update.project_path, + stack_branch=branch, + variables=deploy_update.variables, + start_time=deploy_update.start_time, + destroy_time=deploy_update.destroy_time, + username=current_user.username, + ) # Push task data db_task = crud_tasks.create_task( - db=db, - task_id=pipeline_deploy, - task_name=f"{stack_name}-{squad}-{environment}-{name}", - user_id=current_user.id, - deploy_id=deploy_id, - username=current_user.username, - squad=squad, - action="Update") + db=db, + task_id=pipeline_deploy, + task_name=f"{stack_name}-{squad}-{environment}-{name}", + user_id=current_user.id, + deploy_id=deploy_id, + username=current_user.username, + squad=squad, + action="Update", + ) return {"task": db_task} except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") finally: - result = async_schedule_delete(deploy_id, squad) + async_schedule_delete(deploy_id, squad) # Add schedule async_schedule_add(deploy_id, squad) @router.put("/{deploy_id}", status_code=202) async def destroy_infra( - deploy_id: int, - response: Response, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + deploy_id: int, + response: Response, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): response.status_code = status.HTTP_202_ACCEPTED # Get info from deploy data @@ -204,7 +213,9 @@ async def destroy_infra( squad = deploy_data.squad if not crud_users.is_master(db, current_user): if not check_squad_user(current_user.squad, [deploy_data.squad]): - raise HTTPException(status_code=403, detail=f"Not enough permissions in {squad}") + raise HTTPException( + status_code=403, detail=f"Not enough permissions in {squad}" + ) stack_name = deploy_data.stack_name environment = deploy_data.environment start_time = deploy_data.start_time @@ -215,10 +226,15 @@ async def destroy_infra( name = deploy_data.name # Get credentials by providers supported secreto = tokens.check_prefix( - db, stack_name=stack_name, environment=environment, squad=squad) + db, stack_name=stack_name, environment=environment, squad=squad + ) # Get info from stack data stack_data = stack(db, stack_name=stack_name) - branch = stack_data.branch if deploy_data.stack_branch == "" or deploy_data.stack_branch == None else deploy_data.stack_branch + branch = ( + stack_data.branch + if deploy_data.stack_branch == "" or deploy_data.stack_branch == None + else deploy_data.stack_branch + ) git_repo = stack_data.git_repo tf_ver = stack_data.tf_version # check task pending state @@ -229,101 +245,105 @@ async def destroy_infra( raise ValueError("Deploy state running, cannot upgrade") # push task destroy to queue and return task_id pipeline_destroy = async_destroy( - git_repo, - name, - stack_name, - environment, - squad, - branch, - tf_ver, - variables, - secreto, - tfvar_file, - project_path - ) + git_repo, + name, + stack_name, + environment, + squad, + branch, + tf_ver, + variables, + secreto, + tfvar_file, + project_path, + ) # Push deploy task data crud_deploys.update_deploy( - db=db, - deploy_id=deploy_id, - task_id=pipeline_destroy, - action="Destroy", - user_id=current_user.id, - start_time=start_time, - destroy_time=destroy_time, - stack_branch=branch, - tfvar_file=tfvar_file, - project_path=project_path, - variables=variables, - username=current_user.username) + db=db, + deploy_id=deploy_id, + task_id=pipeline_destroy, + action="Destroy", + user_id=current_user.id, + start_time=start_time, + destroy_time=destroy_time, + stack_branch=branch, + tfvar_file=tfvar_file, + project_path=project_path, + variables=variables, + username=current_user.username, + ) # Push task data db_task = crud_tasks.create_task( - db=db, - task_id=pipeline_destroy, - task_name=f"{stack_name}-{squad}-{environment}-{name}", - user_id=current_user.id, - deploy_id=deploy_id, - username=current_user.username, - squad=squad, - action="Destroy") + db=db, + task_id=pipeline_destroy, + task_name=f"{stack_name}-{squad}-{environment}-{name}", + user_id=current_user.id, + deploy_id=deploy_id, + username=current_user.username, + squad=squad, + action="Destroy", + ) return {"task": db_task} except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") @router.get("/") async def get_all_deploys( - current_user: schemas.User = Depends(deps.get_current_active_user), - skip: int = 0, - limit: int = 100, - db: Session = Depends(deps.get_db)): + current_user: schemas.User = Depends(deps.get_current_active_user), + skip: int = 0, + limit: int = 100, + db: Session = Depends(deps.get_db), +): try: if not crud_users.is_master(db, current_user): squad = current_user.squad - return crud_deploys.get_all_deploys_by_squad(db=db, squad=squad, skip=skip, limit=limit) + return crud_deploys.get_all_deploys_by_squad( + db=db, squad=squad, skip=skip, limit=limit + ) return crud_deploys.get_all_deploys(db=db, skip=skip, limit=limit) except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") @router.get("/{deploy_id}") async def get_deploy_by_id( - deploy_id: int, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + deploy_id: int, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): - result = crud_deploys.get_deploy_by_id( - db=db, deploy_id=deploy_id) + result = crud_deploys.get_deploy_by_id(db=db, deploy_id=deploy_id) if not crud_users.is_master(db, current_user): if not check_squad_user(current_user.squad, [result.squad]): - raise HTTPException(status_code=403, detail=f"Not enough permissions in {result.squad}") + raise HTTPException( + status_code=403, detail=f"Not enough permissions in {result.squad}" + ) try: if result is None: raise HTTPException(status_code=404, detail="Deploy id Not Found") return result except Exception as err: print(err) - raise HTTPException( - status_code=404, - detail=f"{err}") + raise HTTPException(status_code=404, detail=f"{err}") @router.delete("/{deploy_id}") async def delete_infra_by_id( - deploy_id: int, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + deploy_id: int, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): # Get info from deploy data deploy_data = deploy(db, deploy_id=deploy_id) squad = deploy_data.squad if not crud_users.is_master(db, current_user): if not check_squad_user(current_user.squad, [deploy_data.squad]): - raise HTTPException(status_code=403, detail=f"Not enough permissions in {squad}") + raise HTTPException( + status_code=403, detail=f"Not enough permissions in {squad}" + ) stack_name = deploy_data.stack_name environment = deploy_data.environment name = deploy_data.name @@ -332,10 +352,15 @@ async def delete_infra_by_id( variables = deploy_data.variables # Get credentials by providers supported secreto = tokens.check_prefix( - db, stack_name=stack_name, environment=environment, squad=squad) + db, stack_name=stack_name, environment=environment, squad=squad + ) # Get info from stack data stack_data = stack(db, stack_name=stack_name) - branch = stack_data.branch if deploy_data.stack_branch == "" or deploy_data.stack_branch == None else deploy_data.stack_branch + branch = ( + stack_data.branch + if deploy_data.stack_branch == "" or deploy_data.stack_branch == None + else deploy_data.stack_branch + ) git_repo = stack_data.git_repo tf_ver = stack_data.tf_version try: @@ -343,56 +368,54 @@ async def delete_infra_by_id( if not check_deploy_state(deploy_data.task_id): raise ValueError("Deploy state running, cannot upgrade") # Delete deploy db by id - crud_deploys.delete_deploy_by_id( - db=db, - deploy_id=deploy_id, - squad=squad - ) + crud_deploys.delete_deploy_by_id(db=db, deploy_id=deploy_id, squad=squad) # push task destroy to queue and return task_id pipeline_destroy = async_destroy( - git_repo, - name, - stack_name, - environment, - squad, - branch, - tf_ver, - variables, - secreto, - tfvar_file, - project_path - ) + git_repo, + name, + stack_name, + environment, + squad, + branch, + tf_ver, + variables, + secreto, + tfvar_file, + project_path, + ) # Push task data db_task = crud_tasks.create_task( - db=db, - task_id=pipeline_destroy, - task_name=f"{deploy_data.stack_name}-{squad}-{deploy_data.environment}-{deploy_data.name}", - user_id=current_user.id, - deploy_id=deploy_id, - username=current_user.username, - squad=squad, - action="Delete") + db=db, + task_id=pipeline_destroy, + task_name=f"{deploy_data.stack_name}-{squad}-{deploy_data.environment}-{deploy_data.name}", + user_id=current_user.id, + deploy_id=deploy_id, + username=current_user.username, + squad=squad, + action="Delete", + ) return {"task": db_task} except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") finally: - result = async_schedule_delete(deploy_id, squad) + async_schedule_delete(deploy_id, squad) @router.get("/output/{deploy_id}", status_code=200) async def get_output( - deploy_id: int, - db: Session = Depends(deps.get_db), - current_user: schemas.User = Depends(deps.get_current_active_user)): + deploy_id: int, + db: Session = Depends(deps.get_db), + current_user: schemas.User = Depends(deps.get_current_active_user), +): # Get info from deploy data deploy_data = deploy(db, deploy_id=deploy_id) squad = deploy_data.squad if not crud_users.is_master(db, current_user): if not check_squad_user(current_user.squad, [squad]): - raise HTTPException(status_code=403, detail=f"Not enough permissions in {squad}") + raise HTTPException( + status_code=403, detail=f"Not enough permissions in {squad}" + ) try: stack_name = deploy_data.stack_name environment = deploy_data.environment @@ -400,22 +423,23 @@ async def get_output( # Get credentials by providers supported return {"task": async_output(stack_name, environment, squad, name)} except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") @router.put("/unlock/{deploy_id}", status_code=200) async def unlock_deploy( - deploy_id: int, - db: Session = Depends(deps.get_db), - current_user: schemas.User = Depends(deps.get_current_active_user)): + deploy_id: int, + db: Session = Depends(deps.get_db), + current_user: schemas.User = Depends(deps.get_current_active_user), +): # Get info from deploy data deploy_data = deploy(db, deploy_id=deploy_id) squad = deploy_data.squad if not crud_users.is_master(db, current_user): if not check_squad_user(current_user.squad, [squad]): - raise HTTPException(status_code=403, detail=f"Not enough permissions in {squad}") + raise HTTPException( + status_code=403, detail=f"Not enough permissions in {squad}" + ) try: stack_name = deploy_data.stack_name environment = deploy_data.environment @@ -423,16 +447,15 @@ async def unlock_deploy( # Get credentials by providers supported return {"task": async_unlock(stack_name, environment, squad, name)} except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") @router.get("/show/{deploy_id}", status_code=202) async def get_show( - deploy_id: int, - db: Session = Depends(deps.get_db), - current_user: schemas.User = Depends(deps.get_current_active_user)): + deploy_id: int, + db: Session = Depends(deps.get_db), + current_user: schemas.User = Depends(deps.get_current_active_user), +): # Get info from deploy data if crud_users.is_master(db, current_user): deploy_data = deploy(db, deploy_id=deploy_id) @@ -447,6 +470,4 @@ async def get_show( try: return {"task": async_show(stack_name, environment, squad, name)} except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") diff --git a/sld-api-backend/api_v1/endpoints/gcp.py b/sld-api-backend/api_v1/endpoints/gcp.py index ed6b2ea6..7aea5935 100644 --- a/sld-api-backend/api_v1/endpoints/gcp.py +++ b/sld-api-backend/api_v1/endpoints/gcp.py @@ -1,73 +1,78 @@ -from sqlalchemy.orm import Session -from fastapi import APIRouter, Depends, HTTPException, Response - -from schemas import schemas +from crud import activityLogs as crud_activity from crud import gcp as crud_gcp from crud import user as crud_users -from crud import activityLogs as crud_activity +from fastapi import APIRouter, Depends, HTTPException, Response +from schemas import schemas from security import deps - +from sqlalchemy.orm import Session router = APIRouter() @router.post("/", status_code=200) async def create_new_gcloud_profile( - gcp: schemas.GcloudBase, - response: Response, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + gcp: schemas.GcloudBase, + response: Response, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): if not crud_users.is_master(db, current_user): raise HTTPException(status_code=403, detail="Not enough permissions") if "string" in [gcp.squad, gcp.environment]: raise HTTPException( status_code=409, - detail="The squad or environment field must have a value that is not a string.") + detail="The squad or environment field must have a value that is not a string.", + ) db_gcp_account = crud_gcp.get_squad_gcloud_profile( - db=db, squad=gcp.squad, environment=gcp.environment) + db=db, squad=gcp.squad, environment=gcp.environment + ) if db_gcp_account: - raise HTTPException( - status_code=409, - detail="Account already exists") + raise HTTPException(status_code=409, detail="Account already exists") try: result = crud_gcp.create_gcloud_profile( db=db, squad=gcp.squad, environment=gcp.environment, - gcloud_keyfile_json=gcp.gcloud_keyfile_json) + gcloud_keyfile_json=gcp.gcloud_keyfile_json, + ) crud_activity.create_activity_log( db=db, username=current_user.username, squad=current_user.squad, - action=f'Create GCP account {result.id}' + action=f"Create GCP account {result.id}", ) - return {"result": f'Create GCP account {gcp.squad} {gcp.environment}'} + return {"result": f"Create GCP account {gcp.squad} {gcp.environment}"} except Exception as err: raise HTTPException(status_code=400, detail=err) @router.get("/") async def get_all_gcloud_accounts( - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): if not crud_users.is_master(db, current_user): - return crud_gcp.get_squad_gcloud_profile(db=db, squad=current_user.squad, environment=None) + return crud_gcp.get_squad_gcloud_profile( + db=db, squad=current_user.squad, environment=None + ) return crud_gcp.get_all_gcloud_profile(db=db) @router.delete("/{gcloud_account_id}") async def delete_gcloud_account_by_id( - gcloud_account_id, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + gcloud_account_id, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): if not crud_users.is_master(db, current_user): raise HTTPException(status_code=400, detail="Not enough permissions") result = crud_gcp.delete_gcloud_profile_by_id( - db=db, gcloud_profile_id=gcloud_account_id) + db=db, gcloud_profile_id=gcloud_account_id + ) crud_activity.create_activity_log( db=db, username=current_user.username, squad=current_user.squad, - action=f'Delete GCP account {gcloud_account_id} squad' + action=f"Delete GCP account {gcloud_account_id} squad", ) return result diff --git a/sld-api-backend/api_v1/endpoints/healthy.py b/sld-api-backend/api_v1/endpoints/healthy.py index db6cb458..7a738554 100644 --- a/sld-api-backend/api_v1/endpoints/healthy.py +++ b/sld-api-backend/api_v1/endpoints/healthy.py @@ -1,7 +1,6 @@ -from sqlalchemy.orm import Session from fastapi import APIRouter, Depends - from security import deps +from sqlalchemy.orm import Session router = APIRouter() diff --git a/sld-api-backend/api_v1/endpoints/plan.py b/sld-api-backend/api_v1/endpoints/plan.py index a6a64734..235662ae 100644 --- a/sld-api-backend/api_v1/endpoints/plan.py +++ b/sld-api-backend/api_v1/endpoints/plan.py @@ -1,52 +1,47 @@ -from sqlalchemy.orm import Session -from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Response, status - -from schemas import schemas -from security import deps -from security import tokens -from helpers.get_data import check_deploy_state -from helpers.get_data import deploy, deploy_squad, stack -from helpers.push_task import async_plan from crud import deploys as crud_deploys from crud import tasks as crud_tasks from crud import user as crud_users -from helpers.get_data import check_deploy_exist, check_deploy_state, check_cron_schedule -from helpers.get_data import check_squad_user - +from fastapi import (APIRouter, BackgroundTasks, Depends, HTTPException, + Response, status) +from helpers.get_data import (check_cron_schedule, check_deploy_exist, + check_deploy_state, check_squad_user, deploy, + stack) +from helpers.push_task import async_plan +from schemas import schemas +from security import deps, tokens +from sqlalchemy.orm import Session router = APIRouter() @router.post("/", status_code=202) async def plan_infra_by_stack_name( - response: Response, - background_tasks: BackgroundTasks, - deploy: schemas.PlanCreate, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + response: Response, + background_tasks: BackgroundTasks, + deploy: schemas.PlanCreate, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): response.status_code = status.HTTP_202_ACCEPTED squad = deploy.squad # Get squad from current user if not crud_users.is_master(db, current_user): current_squad = current_user.squad - if not check_squad_user(current_user.squad, [deploy.squad]): - raise HTTPException(status_code=403, detail=f"Not enough permissions in {squad}") + if not check_squad_user(current_squad, [deploy.squad]): + raise HTTPException( + status_code=403, detail=f"Not enough permissions in {squad}" + ) # Get credentials by providers supported secreto = tokens.check_prefix( - db, stack_name=deploy.stack_name, environment=deploy.environment, squad=squad) + db, stack_name=deploy.stack_name, environment=deploy.environment, squad=squad + ) # Get info from stack data stack_data = stack(db, stack_name=deploy.stack_name) branch = stack_data.branch if deploy.stack_branch == "" else deploy.stack_branch git_repo = stack_data.git_repo tf_ver = stack_data.tf_version - check_deploy_exist( - db, - deploy.name, - squad, - deploy.environment, - deploy.stack_name - ) + check_deploy_exist(db, deploy.name, squad, deploy.environment, deploy.stack_name) try: # push task Deploy to queue and return task_id pipeline_plan = async_plan( @@ -60,7 +55,8 @@ async def plan_infra_by_stack_name( deploy.variables, secreto, deploy.tfvar_file, - deploy.project_path) + deploy.project_path, + ) # Push deploy task data db_deploy = crud_deploys.create_new_deploy( db=db, @@ -70,7 +66,8 @@ async def plan_infra_by_stack_name( action="Plan", squad=squad, user_id=current_user.id, - username=current_user.username) + username=current_user.username, + ) # Push task data db_task = crud_tasks.create_task( db=db, @@ -80,23 +77,22 @@ async def plan_infra_by_stack_name( deploy_id=db_deploy.id, username=current_user.username, squad=squad, - action="Plan" + action="Plan", ) return {"task": pipeline_plan} except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") @router.patch("/{plan_id}", status_code=202) async def update_plan_by_id( - plan_id: int, - background_tasks: BackgroundTasks, - deploy_update: schemas.DeployUpdate, - response: Response, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + plan_id: int, + background_tasks: BackgroundTasks, + deploy_update: schemas.DeployUpdate, + response: Response, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): response.status_code = status.HTTP_202_ACCEPTED # Get info from deploy data @@ -107,10 +103,13 @@ async def update_plan_by_id( name = deploy_data.name if not crud_users.is_master(db, current_user): if not check_squad_user(current_user.squad, [squad]): - raise HTTPException(status_code=403, detail=f"Not enough permissions in {squad}") + raise HTTPException( + status_code=403, detail=f"Not enough permissions in {squad}" + ) # Get credentials by providers supported secreto = tokens.check_prefix( - db, stack_name=stack_name, environment=environment, squad=squad) + db, stack_name=stack_name, environment=environment, squad=squad + ) # Get info from stack data stack_data = stack(db, stack_name=stack_name) if not deploy_update.stack_branch: @@ -142,8 +141,8 @@ async def update_plan_by_id( deploy_update.variables, secreto, deploy_update.tfvar_file, - deploy_update.project_path - ) + deploy_update.project_path, + ) # Push deploy task data crud_deploys.update_deploy( db=db, @@ -157,7 +156,8 @@ async def update_plan_by_id( variables=deploy_update.variables, start_time=deploy_update.start_time, destroy_time=deploy_update.destroy_time, - username=current_user.username) + username=current_user.username, + ) action = "Plan" # Push task data db_task = crud_tasks.create_task( @@ -168,30 +168,36 @@ async def update_plan_by_id( deploy_id=plan_id, username=current_user.username, squad=squad, - action=action) + action=action, + ) return {"task": pipeline_plan} except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") @router.get("/{deploy_id}", status_code=202) async def get_plan_by_id_deploy( - deploy_id: int, - response: Response, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + deploy_id: int, + response: Response, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): response.status_code = status.HTTP_202_ACCEPTED deploy_data = deploy(db, deploy_id=deploy_id) if not crud_users.is_master(db, current_user): if not check_squad_user(current_user.squad, [deploy_data.squad]): - raise HTTPException(status_code=403, detail=f"Not enough permissions in {deploy_data.squad}") + raise HTTPException( + status_code=403, detail=f"Not enough permissions in {deploy_data.squad}" + ) # Get credentials by providers supported secreto = tokens.check_prefix( - db, stack_name=deploy_data.stack_name, environment=deploy_data.environment, squad=deploy_data.squad) + db, + stack_name=deploy_data.stack_name, + environment=deploy_data.environment, + squad=deploy_data.squad, + ) # Get info from stack data stack_data = stack(db, stack_name=deploy_data.stack_name) branch = deploy_data.stack_branch @@ -213,9 +219,8 @@ async def get_plan_by_id_deploy( deploy_data.variables, secreto, deploy_data.tfvar_file, - deploy_data.project_path) + deploy_data.project_path, + ) return {"task": pipeline_plan} except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") diff --git a/sld-api-backend/api_v1/endpoints/schedule.py b/sld-api-backend/api_v1/endpoints/schedule.py index 98d7d7cc..acd20290 100644 --- a/sld-api-backend/api_v1/endpoints/schedule.py +++ b/sld-api-backend/api_v1/endpoints/schedule.py @@ -1,79 +1,80 @@ -from sqlalchemy.orm import Session -from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Response, status - -from schemas import schemas from crud import deploys as crud_deploys from crud import tasks as crud_tasks from crud import user as crud_users +from fastapi import (APIRouter, BackgroundTasks, Depends, HTTPException, + Response, status) +from helpers.get_data import (check_cron_schedule, check_squad_user, deploy, + deploy_squad) +from helpers.push_task import (async_schedule_add, async_schedule_delete, + async_schedule_get, async_schedule_list, + async_schedule_update) +from schemas import schemas from security import deps -from security import tokens -from helpers.get_data import check_cron_schedule, check_squad_user -from helpers.get_data import check_deploy_exist, check_deploy_state -from helpers.get_data import stack, deploy, deploy_squad, check_deploy_exist -from helpers.push_task import async_schedule_list, async_schedule_get, async_schedule_add, async_schedule_delete, async_schedule_update - +from sqlalchemy.orm import Session router = APIRouter() @router.get("/list/", status_code=202) async def list_schedules( - db: Session = Depends(deps.get_db), - current_user: schemas.User = Depends(deps.get_current_active_user)): + db: Session = Depends(deps.get_db), + current_user: schemas.User = Depends(deps.get_current_active_user), +): squad = current_user.squad try: return {"task_id": async_schedule_list(squad=squad)} except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") @router.get("/{deploy_id}", status_code=202) async def get_schedule( - deploy_id: int, - db: Session = Depends(deps.get_db), - current_user: schemas.User = Depends(deps.get_current_active_user)): + deploy_id: int, + db: Session = Depends(deps.get_db), + current_user: schemas.User = Depends(deps.get_current_active_user), +): # Get info from deploy data deploy_data = deploy(db, deploy_id=deploy_id) squad = deploy_data.squad deploy_name = deploy_data.id if not crud_users.is_master(db, current_user): if not check_squad_user(current_user.squad, [squad]): - raise HTTPException(status_code=403, detail=f"Not enough permissions in {squad}") + raise HTTPException( + status_code=403, detail=f"Not enough permissions in {squad}" + ) try: return {"task_id": async_schedule_get(deploy_name=deploy_name, squad=squad)} except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") @router.post("/{deploy_id}", status_code=202) async def add_schedule( - deploy_id: int, - db: Session = Depends(deps.get_db), - current_user: schemas.User = Depends(deps.get_current_active_user)): + deploy_id: int, + db: Session = Depends(deps.get_db), + current_user: schemas.User = Depends(deps.get_current_active_user), +): # Get info from deploy data deploy_data = deploy(db, deploy_id=deploy_id) squad = deploy_data.squad deploy_name = deploy_data.id if not crud_users.is_master(db, current_user): if not check_squad_user(current_user.squad, [squad]): - raise HTTPException(status_code=403, detail=f"Not enough permissions in {squad}") + raise HTTPException( + status_code=403, detail=f"Not enough permissions in {squad}" + ) try: - return {"task_id":async_schedule_add(deploy_name=deploy_name, squad=squad)} + return {"task_id": async_schedule_add(deploy_name=deploy_name, squad=squad)} except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") @router.delete("/{deploy_id}", status_code=202) async def delete_schedule( - deploy_id: int, - db: Session = Depends(deps.get_db), - current_user: schemas.User = Depends(deps.get_current_active_user)): + deploy_id: int, + db: Session = Depends(deps.get_db), + current_user: schemas.User = Depends(deps.get_current_active_user), +): # Get info from deploy data if crud_users.is_master(db, current_user): deploy_data = deploy(db, deploy_id=deploy_id) @@ -84,21 +85,20 @@ async def delete_schedule( deploy_data = deploy_squad(db, deploy_id=deploy_id, squad=squad) deploy_name = deploy_data.id try: - return {"task_id":async_schedule_delete(deploy_name=deploy_name, squad=squad)} + return {"task_id": async_schedule_delete(deploy_name=deploy_name, squad=squad)} except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") @router.patch("/{deploy_id}", status_code=202) async def update_schedule( - deploy_id: int, - background_tasks: BackgroundTasks, - deploy_update: schemas.ScheduleUpdate, - response: Response, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + deploy_id: int, + background_tasks: BackgroundTasks, + deploy_update: schemas.ScheduleUpdate, + response: Response, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): response.status_code = status.HTTP_202_ACCEPTED @@ -110,7 +110,9 @@ async def update_schedule( name = deploy_data.name if not crud_users.is_master(db, current_user): if not check_squad_user(current_user.squad, [squad]): - raise HTTPException(status_code=403, detail=f"Not enough permissions in {squad}") + raise HTTPException( + status_code=403, detail=f"Not enough permissions in {squad}" + ) try: # check crontime check_cron_schedule(deploy_update.start_time) @@ -122,7 +124,8 @@ async def update_schedule( db=db, deploy_id=deploy_id, start_time=deploy_update.start_time, - destroy_time=deploy_update.destroy_time) + destroy_time=deploy_update.destroy_time, + ) # Push task data db_task = crud_tasks.create_task( db=db, @@ -132,10 +135,9 @@ async def update_schedule( deploy_id=deploy_id, username=current_user.username, squad=squad, - action="UpdateSchedule") + action="UpdateSchedule", + ) return {"task_id": pipeline_schedule} except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") diff --git a/sld-api-backend/api_v1/endpoints/stacks.py b/sld-api-backend/api_v1/endpoints/stacks.py index 8bdfd9ea..2aa9977c 100644 --- a/sld-api-backend/api_v1/endpoints/stacks.py +++ b/sld-api-backend/api_v1/endpoints/stacks.py @@ -1,25 +1,24 @@ -from sqlalchemy.orm import Session +from crud import activityLogs as crud_activity +from crud import stacks as crud_stacks +from crud import user as crud_users from fastapi import APIRouter, Depends, HTTPException - +from helpers.get_data import (check_providers, check_squad_stack, + check_squad_user) +from helpers.push_task import sync_git from schemas import schemas from security import deps -from crud import user as crud_users -from crud import stacks as crud_stacks -from crud import activityLogs as crud_activity -from helpers.push_task import sync_git, sync_get_vars -from helpers.get_data import check_providers, check_squad_user +from sqlalchemy.orm import Session router = APIRouter() @router.post("/", response_model=schemas.Stack) def create_new_stack( - stack: schemas.StackCreate, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + stack: schemas.StackCreate, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): - if not crud_users.is_master(db, current_user): - raise HTTPException(status_code=403, detail="Not enough permissions") name = "default" environment = "default" squad = "squad" @@ -30,9 +29,9 @@ def create_new_stack( # Check if stack exist db_stack = crud_stacks.get_stack_by_name(db, stack_name=stack.stack_name) if db_stack: - raise HTTPException( - status_code=409, - detail="The stack name already exist") + raise HTTPException(status_code=409, detail="The stack name already exist") + # Check if the user have permissions for create stack + check_squad_stack(db, current_user, current_user.squad, stack.squad_access) # Push git task to queue squad, all workers are subscribed to this queue task = sync_git( stack_name=stack.stack_name, @@ -40,8 +39,9 @@ def create_new_stack( branch=branch, environment=environment, squad=squad, - name=name) - variables_list = [i for i in task[1]['variable'].keys()] + name=name, + ) + variables_list = [i for i in task[1]["variable"].keys()] try: # pesrsist data in db result = crud_stacks.create_new_stack( @@ -51,14 +51,14 @@ def create_new_stack( task_id=task[0], var_json=task[1], var_list=variables_list, - squad_access=stack.squad_access + squad_access=stack.squad_access, ) crud_activity.create_activity_log( db=db, username=current_user.username, squad=current_user.squad, - action=f'Create Stack {stack.stack_name}' + action=f"Create Stack {stack.stack_name}", ) return result except Exception as err: @@ -67,17 +67,18 @@ def create_new_stack( @router.patch("/{stack_id}", response_model=schemas.Stack) def update_stack( - stack_id: int, - stack: schemas.StackCreate, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): - if not crud_users.is_master(db, current_user): - raise HTTPException(status_code=403, detail="Not enough permissions") + stack_id: int, + stack: schemas.StackCreate, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): name = "default" environment = "default" squad = "squad" branch = stack.branch + # Check if the user have permissions for create stack + check_squad_stack(db, current_user, current_user.squad, stack.squad_access) # Checkif stack name providers are supperted check_providers(stack_name=stack.stack_name) # Check if stack exist @@ -89,8 +90,9 @@ def update_stack( branch=branch, environment=environment, squad=squad, - name=name) - variables_list = [i for i in task[1]['variable'].keys()] + name=name, + ) + variables_list = [i for i in task[1]["variable"].keys()] try: # pesrsist data in db result = crud_stacks.update_stack( @@ -101,14 +103,14 @@ def update_stack( task_id=task[0], var_json=task[1], var_list=variables_list, - squad_access=stack.squad_access + squad_access=stack.squad_access, ) crud_activity.create_activity_log( db=db, username=current_user.username, squad=current_user.squad, - action=f'Update Stack {stack.stack_name}' + action=f"Update Stack {stack.stack_name}", ) return result except Exception as err: @@ -117,73 +119,92 @@ def update_stack( @router.get("/") async def get_all_stacks( - current_user: schemas.User = Depends(deps.get_current_active_user), - skip: int = 0, - limit: int = 100, - db: Session = Depends(deps.get_db)): + current_user: schemas.User = Depends(deps.get_current_active_user), + skip: int = 0, + limit: int = 100, + db: Session = Depends(deps.get_db), +): if not crud_users.is_master(db, current_user): - return crud_stacks.get_all_stacks_by_squad(db=db, squad_access=current_user.squad, skip=skip, limit=limit) - return crud_stacks.get_all_stacks(db=db, squad_access=current_user.squad, skip=skip, limit=limit) + return crud_stacks.get_all_stacks_by_squad( + db=db, squad_access=current_user.squad, skip=skip, limit=limit + ) + return crud_stacks.get_all_stacks( + db=db, squad_access=current_user.squad, skip=skip, limit=limit + ) @router.get("/{stack}") async def get_stack_by_id_or_name( - stack, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + stack, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): if not stack.isdigit(): result = crud_stacks.get_stack_by_name(db=db, stack_name=stack) if not crud_users.is_master(db, current_user): if result is None: raise HTTPException(status_code=404, detail="stack id not found") - if not check_squad_user(current_user.squad, result.squad_access) and not "*" in result.squad_access: - raise HTTPException(status_code=403, detail=f"Not enough permissions in {result.squad_access}") + if ( + not check_squad_user(current_user.squad, result.squad_access) + and not "*" in result.squad_access + ): + raise HTTPException( + status_code=403, + detail=f"Not enough permissions in {result.squad_access}", + ) return result result = crud_stacks.get_stack_by_id(db=db, stack_id=stack) if result is None: raise HTTPException(status_code=404, detail="stack id not found") if not crud_users.is_master(db, current_user): - if not check_squad_user(current_user.squad, result.squad_access) and not "*" in result.squad_access: - raise HTTPException(status_code=403, detail=f"Not enough permissions in {result.squad_access}") + if ( + not check_squad_user(current_user.squad, result.squad_access) + and not "*" in result.squad_access + ): + raise HTTPException( + status_code=403, + detail=f"Not enough permissions in {result.squad_access}", + ) return result @router.delete("/{stack}") async def delete_stack_by_id_or_name( - stack, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): - if not crud_users.is_master(db, current_user): - raise HTTPException( - status_code=403, detail="Not enough permissions") + stack, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): try: if not stack.isdigit(): result = crud_stacks.get_stack_by_name(db=db, stack_name=stack) if result is None: raise HTTPException(status_code=404, detail="stack id not found") - if not current_user.squad in result.squad_access and not crud_users.is_master(db, current_user) and not "*" in result.squad_access: - raise HTTPException( - status_code=403, detail="Not enough permissions") + # Check if the user have permissions for create stack + check_squad_stack(db, current_user, current_user.squad, result.squad_access) + crud_activity.create_activity_log( db=db, username=current_user.username, squad=current_user.squad, - action=f'Delete Stack {result.stack_name}' + action=f"Delete Stack {result.stack_name}", ) return crud_stacks.delete_stack_by_name(db=db, stack_name=stack) + result = crud_stacks.get_stack_by_id(db=db, stack_id=stack) if result is None: raise HTTPException(status_code=404, detail="stack id not found") - if not current_user.squad in result.squad_access and not crud_users.is_master(db, current_user) and not "*" in result.squad_access: - raise HTTPException(status_code=403, detail="Not enough permissions") + + # Check if the user have permissions for create stack + check_squad_stack(db, current_user, current_user.squad, result.squad_access) + crud_activity.create_activity_log( db=db, username=current_user.username, squad=current_user.squad, - action=f'Delete Stack {result.id}' + action=f"Delete Stack {result.id}", ) return crud_stacks.delete_stack_by_id(db=db, stack_id=stack) except Exception as err: - return err + raise err diff --git a/sld-api-backend/api_v1/endpoints/tasks.py b/sld-api-backend/api_v1/endpoints/tasks.py index 4309b8f8..0d93b8ae 100644 --- a/sld-api-backend/api_v1/endpoints/tasks.py +++ b/sld-api-backend/api_v1/endpoints/tasks.py @@ -1,17 +1,17 @@ import ast -from sqlalchemy.orm import Session -from fastapi import APIRouter, Depends, HTTPException -from celery.result import AsyncResult -from config.celery_config import celery_app -from schemas import schemas -from security import deps +from celery.result import AsyncResult +from config.celery_config import celery_app from crud import tasks as crud_tasks from crud import user as crud_users +from fastapi import APIRouter, Depends, HTTPException +from schemas import schemas +from security import deps +from sqlalchemy.orm import Session -#from fastapi_limiter import FastAPILimiter -#from fastapi_limiter.depends import RateLimiter -#import aioredis +# from fastapi_limiter import FastAPILimiter +# from fastapi_limiter.depends import RateLimiter +# import aioredis router = APIRouter() @@ -23,56 +23,54 @@ @router.delete("/id/{task_id}") async def get_task_by_id( - task_id: str, - current_user: schemas.User = Depends(deps.get_current_active_user)): + task_id: str, current_user: schemas.User = Depends(deps.get_current_active_user) +): result = celery_app.control.revoke(task_id, terminate=True) - return {"result": f'REVOKE {task_id}'} + return {"result": f"REVOKE {task_id}"} @router.get("/id/{task_id}") async def get_task_by_id( - task_id: str, - current_user: schemas.User = Depends(deps.get_current_active_user)): + task_id: str, current_user: schemas.User = Depends(deps.get_current_active_user) +): a = AsyncResult(task_id) cstr = str(a.info) try: parse = ast.literal_eval(cstr) - except Exception as err: + except Exception: parse = str(cstr) - result = { - "result": { - "state": a.state, "module": parse, "status": a.status}} + result = {"result": {"state": a.state, "module": parse, "status": a.status}} return result -@ router.get("/all") +@router.get("/all") async def get_all_tasks( - current_user: schemas.User = Depends(deps.get_current_active_user), - skip: int = 0, - limit: int = 100, - db: Session = Depends(deps.get_db)): + current_user: schemas.User = Depends(deps.get_current_active_user), + skip: int = 0, + limit: int = 100, + db: Session = Depends(deps.get_db), +): try: if not crud_users.is_master(db, current_user): squad = current_user.squad - result = crud_tasks.get_all_tasks_by_squad(db=db, squad=squad, skip=skip, limit=limit) + result = crud_tasks.get_all_tasks_by_squad( + db=db, squad=squad, skip=skip, limit=limit + ) return result result = crud_tasks.get_all_tasks(db=db, skip=skip, limit=limit) return result except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") -@ router.get("/deploy_id/{id}") +@router.get("/deploy_id/{id}") async def get_task_by_deploy_id( - id: int, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + id: int, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): try: result = crud_tasks.get_tasks_by_deploy_id(db=db, deploy_id=id) return result except Exception as err: - raise HTTPException( - status_code=400, - detail=f"{err}") + raise HTTPException(status_code=400, detail=f"{err}") diff --git a/sld-api-backend/api_v1/endpoints/users.py b/sld-api-backend/api_v1/endpoints/users.py index 5aa60774..2294521b 100644 --- a/sld-api-backend/api_v1/endpoints/users.py +++ b/sld-api-backend/api_v1/endpoints/users.py @@ -1,71 +1,76 @@ -from fastapi import APIRouter, Depends, HTTPException -from sqlalchemy.orm import Session - -from crud import user as crud_users +from config.api import settings from crud import activityLogs as crud_activity -from helpers.get_data import user_squad_scope, activity_log, check_squad_user, check_role_user +from crud import user as crud_users +from fastapi import APIRouter, Depends, HTTPException +from helpers.get_data import (activity_log, check_role_user, check_squad_user, + user_squad_scope) +from schemas.schemas import (PasswordReset, User, UserCreate, UserInit, + UserUpdate) from security import deps -from config.api import settings -from schemas.schemas import ( - User, UserCreate, UserUpdate, PasswordReset, UserInit) - +from sqlalchemy.orm import Session router = APIRouter() @router.post("/start", response_model=User) async def create_init_user(passwd: UserInit, db: Session = Depends(deps.get_db)): - ''' + """ Create init user - ''' + """ deps.validate_password(passwd.password) init_user = settings.INIT_USER - db_user = crud_users.get_user_by_username( - db, username=init_user.get("username")) + db_user = crud_users.get_user_by_username(db, username=init_user.get("username")) if db_user: - raise HTTPException( - status_code=409, - detail="Username already registered") + raise HTTPException(status_code=409, detail="Username already registered") else: try: return crud_users.create_init_user(db=db, password=passwd.password) except Exception as err: - raise HTTPException( - status_code=400, - detail=str(err)) + raise HTTPException(status_code=400, detail=str(err)) @router.post("/", response_model=User) async def create_user( - user: UserCreate, current_user: User = Depends( - deps.get_current_active_user), db: Session = Depends( - deps.get_db)): - ''' + user: UserCreate, + current_user: User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): + """ Create user and define squad and privilege - ''' + """ # Check if the user has privileges if not crud_users.is_superuser(db, current_user): raise HTTPException(status_code=403, detail="Not enough permissions") # Check role - roles = ['yoda', 'darth_vader', 'stormtrooper', 'R2-D2'] + roles = ["yoda", "darth_vader", "stormtrooper", "R2-D2"] if not all(item in roles for item in user.role): - raise HTTPException(status_code=403, detail='Only supported roles "yoda", "darth_vader", "stormtrooper".If the user is a bot you can pass R2-D2 together to a role like this ["yoda", "R2-D2"]') + raise HTTPException( + status_code=403, + detail='Only supported roles "yoda", "darth_vader", "stormtrooper".If the user is a bot you can pass R2-D2 together to a role like this ["yoda", "R2-D2"]', + ) # Check if the user with squad * not have role yoda if "*" in user.squad and "yoda" not in user.role: - raise HTTPException(status_code=403, detail="It is not possible to use * squad when role is not yoda") + raise HTTPException( + status_code=403, + detail="It is not possible to use * squad when role is not yoda", + ) # Get squad from current user if not crud_users.is_master(db, current_user): if not check_squad_user(current_user.squad, user.squad): - raise HTTPException(status_code=403, detail=f"Not enough permissions for some of these squads {user.squad}") + raise HTTPException( + status_code=403, + detail=f"Not enough permissions for some of these squads {user.squad}", + ) if not check_role_user(current_user.role, user.role): - raise HTTPException(status_code=403, detail=f"Not enough permissions for some of these roles {user.role}") + raise HTTPException( + status_code=403, + detail=f"Not enough permissions for some of these roles {user.role}", + ) # Check if user exists db_user = crud_users.get_user_by_username(db, username=user.username) if db_user: - raise HTTPException( - status_code=400, - detail="Username already registered") + raise HTTPException(status_code=400, detail="Username already registered") deps.validate_password(user.password) try: result = crud_users.create_user(db=db, user=user) @@ -73,41 +78,52 @@ async def create_user( db=db, username=current_user.username, squad=user.squad, - action=f'Create User {user.username}' + action=f"Create User {user.username}", ) return result except Exception as err: - raise HTTPException( - status_code=400, - detail=str(err)) + raise HTTPException(status_code=400, detail=str(err)) @router.patch("/{user_id}", response_model=User) async def update_user( - user_id: str, - user: UserUpdate, - current_user: User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): - ''' + user_id: str, + user: UserUpdate, + current_user: User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): + """ Update user - ''' + """ # Check if the user has privileges if not crud_users.is_superuser(db, current_user): raise HTTPException(status_code=403, detail="Not enough permissions") # Check role - roles = ['yoda', 'darth_vader', 'stormtrooper', 'R2-D2'] + roles = ["yoda", "darth_vader", "stormtrooper", "R2-D2"] if not all(item in roles for item in user.role): - raise HTTPException(status_code=403, detail='Only supported roles "yoda", "darth_vader", "stormtrooper".If the user is a bot you can pass R2-D2 together to a role like this ["yoda", "R2-D2"]') + raise HTTPException( + status_code=403, + detail='Only supported roles "yoda", "darth_vader", "stormtrooper".If the user is a bot you can pass R2-D2 together to a role like this ["yoda", "R2-D2"]', + ) # Check if the user with squad * not have role yoda if "*" in user.squad and "yoda" not in user.role: - raise HTTPException(status_code=403, detail="It is not possible to use * squad when role is not yoda") + raise HTTPException( + status_code=403, + detail="It is not possible to use * squad when role is not yoda", + ) # Get squad from current user if not crud_users.is_master(db, current_user): current_squad = current_user.squad - if not check_squad_user(current_user.squad, user.squad): - raise HTTPException(status_code=403, detail=f"Not enough permissions for some of these squads {user.squad}") + if not check_squad_user(current_squad, user.squad): + raise HTTPException( + status_code=403, + detail=f"Not enough permissions for some of these squads {user.squad}", + ) if not check_role_user(current_user.role, user.role): - raise HTTPException(status_code=403, detail=f"Not enough permissions for some of these roles {user.role}") + raise HTTPException( + status_code=403, + detail=f"Not enough permissions for some of these roles {user.role}", + ) check_None = [None, "", "string"] if user.password not in check_None: deps.validate_password(user.password) @@ -118,70 +134,68 @@ async def update_user( db=db, username=current_user.username, squad=user.squad, - action=f'Update user {result.username}' + action=f"Update user {result.username}", ) return result except Exception as err: - raise HTTPException( - status_code=400, - detail=str(err)) + raise HTTPException(status_code=400, detail=str(err)) @router.patch("/reset/") async def password_reset( - passwd: PasswordReset, - current_user: User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): - ''' + passwd: PasswordReset, + current_user: User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): + """ reset user - ''' + """ user_id = current_user.id deps.validate_password(passwd.passwd) try: - result = crud_users.password_reset( - db=db, user_id=user_id, password=passwd) + result = crud_users.password_reset(db=db, user_id=user_id, password=passwd) db_task = crud_activity.create_activity_log( db=db, username=current_user.username, squad=current_user.squad, - action=f'Reset password' + action=f"Reset password", ) return {"result": "Password updated"} except Exception as err: - raise HTTPException( - status_code=400, - detail=str(err)) + raise HTTPException(status_code=400, detail=str(err)) @router.get("/") async def list_users( - current_user: User = Depends(deps.get_current_active_user), - skip: int = 0, - limit: int = 100, - db: Session = Depends(deps.get_db)): - ''' + current_user: User = Depends(deps.get_current_active_user), + skip: int = 0, + limit: int = 100, + db: Session = Depends(deps.get_db), +): + """ List users - ''' + """ if not crud_users.is_superuser(db, current_user): raise HTTPException(status_code=403, detail="Not enough permissions") try: if not crud_users.is_master(db, current_user): - return crud_users.get_users_by_squad(db=db, squad=current_user.squad, skip=skip, limit=limit) + return crud_users.get_users_by_squad( + db=db, squad=current_user.squad, skip=skip, limit=limit + ) return crud_users.get_users(db=db, skip=skip, limit=limit) except Exception as err: - raise HTTPException( - status_code=400, - detail=str(err)) + raise HTTPException(status_code=400, detail=str(err)) @router.get("/{user}") async def list_user_by_id_or_name( - user, - current_user: User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): - ''' + user, + current_user: User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): + """ List user by id or name - ''' + """ if crud_users.is_master(db, current_user): if not user.isdigit(): return crud_users.get_user_by_username(db=db, username=user) @@ -196,17 +210,16 @@ async def list_user_by_id_or_name( return crud_users.get_user_by_username(db=db, username=user) return crud_users.get_user_by_id(db=db, id=user) except Exception as err: - raise HTTPException( - status_code=400, - detail=str(err)) + raise HTTPException(status_code=400, detail=str(err)) @router.delete("/{user}") @activity_log async def delete_user_by_id_or_username( - user, - current_user: User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + user, + current_user: User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): if crud_users.is_master(db, current_user): if not user.isdigit(): @@ -222,6 +235,4 @@ async def delete_user_by_id_or_username( result = crud_users.delete_user_by_id(db=db, id=user) return result except Exception as err: - raise HTTPException( - status_code=400, - detail=str(err)) + raise HTTPException(status_code=400, detail=str(err)) diff --git a/sld-api-backend/api_v1/endpoints/variables.py b/sld-api-backend/api_v1/endpoints/variables.py index 6932d5b0..b3eece55 100644 --- a/sld-api-backend/api_v1/endpoints/variables.py +++ b/sld-api-backend/api_v1/endpoints/variables.py @@ -1,26 +1,24 @@ -from sqlalchemy.orm import Session -from fastapi import APIRouter, Depends, HTTPException - - -from schemas import schemas -from crud import stacks as crud_stacks from crud import deploys as crud_deploys +from crud import stacks as crud_stacks from crud import user as crud_users -from security import deps +from fastapi import APIRouter, Depends, HTTPException from helpers.get_data import check_squad_user - +from schemas import schemas +from security import deps +from sqlalchemy.orm import Session router = APIRouter() @router.get("/json") async def get_json( - stack, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): - ''' + stack, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): + """ Pass the name of the stack or the id, and I will return the variables supported by the stack as json format - ''' + """ try: if stack.isdigit(): result = crud_stacks.get_stack_by_id(db=db, stack_id=stack) @@ -29,19 +27,18 @@ async def get_json( result = crud_stacks.get_stack_by_name(db=db, stack_name=stack) return result.var_json.get("variable") except Exception as err: - raise HTTPException( - status_code=404, - detail=f"{err}") + raise HTTPException(status_code=404, detail=f"{err}") -@ router.get("/list") +@router.get("/list") async def get_list( - stack, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): - ''' + stack, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): + """ Pass the name of the stack or the id, and I will return the variables supported by the stack as list format - ''' + """ try: if stack.isdigit(): result = crud_stacks.get_stack_by_id(db=db, stack_id=stack) @@ -50,26 +47,25 @@ async def get_list( result = crud_stacks.get_stack_by_name(db=db, stack_name=stack) return result.var_list except Exception as err: - raise HTTPException( - status_code=404, - detail=f"{err}") + raise HTTPException(status_code=404, detail=f"{err}") @router.get("/deploy/{deploy_id}") async def get_deploy_by_id( - deploy_id: int, - current_user: schemas.User = Depends(deps.get_current_active_user), - db: Session = Depends(deps.get_db)): + deploy_id: int, + current_user: schemas.User = Depends(deps.get_current_active_user), + db: Session = Depends(deps.get_db), +): result = crud_deploys.get_deploy_by_id(db=db, deploy_id=deploy_id) if not crud_users.is_master(db, current_user): if not check_squad_user(current_user.squad, [result.squad]): - raise HTTPException(status_code=403, detail=f"Not enough permissions in {squad}") + raise HTTPException( + status_code=403, detail=f"Not enough permissions in {squad}" + ) try: if result is None: raise Exception("Deploy id Not Found") return result.variables except Exception as err: - raise HTTPException( - status_code=404, - detail=f"{err}") + raise HTTPException(status_code=404, detail=f"{err}") diff --git a/sld-api-backend/config/api.py b/sld-api-backend/config/api.py index 91d1dc96..49ed526e 100644 --- a/sld-api-backend/config/api.py +++ b/sld-api-backend/config/api.py @@ -1,55 +1,62 @@ -from typing import List import os +from typing import List from pydantic import BaseSettings class Settings(BaseSettings): - #Schedle config - SCHEDULE_SERVER: str = os.getenv('SLD_SCHEDULE_SERVER', "http://schedule:10000") + # Schedle config + SCHEDULE_SERVER: str = os.getenv("SLD_SCHEDULE_SERVER", "http://schedule:10000") # API server config API_V1_STR: str = "/api/v1" PROJECT_NAME: str = "API Stack Lifecycle Deployment" - DESCRIPTION: str = ''' + DESCRIPTION: str = """ OpenSource solution that defines and manages the complete lifecycle of resources used and provisioned into a cloud - ''' + """ VERSION: str = "1.0.0" AWS_PREFIX: List = ["aws"] GCLOUD_PREFIX: List = ["gcp"] AZURE_PREFIX: List = ["azure"] PROVIDERS_SUPPORT: List = AWS_PREFIX + GCLOUD_PREFIX + AZURE_PREFIX - SECRET_KEY: str = os.getenv('SLD_SECRET_KEY', "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7") + SECRET_KEY: str = os.getenv( + "SLD_SECRET_KEY", + "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7", + ) ALGORITHM = "HS256" # 60 minutes * 24 hours * 8 days = 8 days ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 24 * 8 - SECRET_VAULT: bytes = os.getenv('SLD_SECRET_VAULT', b'h0aW9hCz_wmEplvlFdoWjqx2pund1gGlcoZ2eqvYpCM=') - PASSWORD_LEN: int = os.getenv('SLD_PASSWORD_LEN', 8) - ROLLBACK: bool = os.getenv('SLD_ROLLBACK', False) - DEPLOY_TMOUT: int =os.getenv('SLD_DEPLOY_TMOUT', 7200 ) - GIT_TMOUT: int =os.getenv('SLD_GIT_TMOUT',15 ) - WORKER_TMOUT: int =os.getenv('SLD_WORKER_TMOUT', 300 ) - ENV: str = os.getenv('SLD_ENV', "dev") - DEBUG: bool = os.getenv('SLD_DEBUG', False) - BACKEND_USER = os.getenv('BACKEND_USER', "") - BACKEND_PASSWD = os.getenv('BACKEND_PASSWD', "") - BACKEND_SERVER = os.getenv('BACKEND_SERVER', "redis") - #init user + SECRET_VAULT: bytes = os.getenv( + "SLD_SECRET_VAULT", b"h0aW9hCz_wmEplvlFdoWjqx2pund1gGlcoZ2eqvYpCM=" + ) + PASSWORD_LEN: int = os.getenv("SLD_PASSWORD_LEN", 8) + ROLLBACK: bool = os.getenv("SLD_ROLLBACK", False) + DEPLOY_TMOUT: int = os.getenv("SLD_DEPLOY_TMOUT", 7200) + GIT_TMOUT: int = os.getenv("SLD_GIT_TMOUT", 15) + WORKER_TMOUT: int = os.getenv("SLD_WORKER_TMOUT", 300) + ENV: str = os.getenv("SLD_ENV", "dev") + DEBUG: bool = os.getenv("SLD_DEBUG", False) + BACKEND_USER = os.getenv("BACKEND_USER", "") + BACKEND_PASSWD = os.getenv("BACKEND_PASSWD", "") + BACKEND_SERVER = os.getenv("BACKEND_SERVER", "redis") + # init user INIT_USER = { - "username": os.getenv('SLD_INIT_USER_NAME', "admin"), - "fullname": os.getenv('SLD_INIT_USER_FULLNAME', "Master of the universe user"), - "email": os.getenv('SLD_INIT_USER_email', "admin@example.com") + "username": os.getenv("SLD_INIT_USER_NAME", "admin"), + "fullname": os.getenv("SLD_INIT_USER_FULLNAME", "Master of the universe user"), + "email": os.getenv("SLD_INIT_USER_email", "admin@example.com"), } AWS_CONGIG_DEFAULT_FOLDER: str = f"{os.environ['HOME']}/.aws" AWS_SHARED_CREDENTIALS_FILE: str = f"{AWS_CONGIG_DEFAULT_FOLDER}/credentials" AWS_SHARED_CONFIG_FILE: str = f"{AWS_CONGIG_DEFAULT_FOLDER}/config" - TASK_MAX_RETRY: int = os.getenv('SLD_TASK_MAX_RETRY', 1) - TASK_RETRY_INTERVAL: int = os.getenv('SLD_TASK_RETRY_INTERVAL', 20) - TASK_LOCKED_EXPIRED = os.getenv('SLD_TASK_LOCKED_EXPIRED', 3600) - TASK_ROUTE: bool = os.getenv('SLD_TASK_ROUTE', False) - TERRAFORM_BIN_REPO: str = os.getenv('SLD_TERRAFORM_BIN_REPO', "https://releases.hashicorp.com/terraform") - REMOTE_STATE: str = os.getenv('SLD_REMOTE_STATE', "http://remote-state:8080") - BOT: str = os.getenv('SLD_API_SERVER_USER', 'schedule') - BOTC: str = os.getenv('SLD_API_SERVER_PASSWORD', 'Schedule1@local') + TASK_MAX_RETRY: int = os.getenv("SLD_TASK_MAX_RETRY", 1) + TASK_RETRY_INTERVAL: int = os.getenv("SLD_TASK_RETRY_INTERVAL", 20) + TASK_LOCKED_EXPIRED = os.getenv("SLD_TASK_LOCKED_EXPIRED", 3600) + TASK_ROUTE: bool = os.getenv("SLD_TASK_ROUTE", False) + TERRAFORM_BIN_REPO: str = os.getenv( + "SLD_TERRAFORM_BIN_REPO", "https://releases.hashicorp.com/terraform" + ) + REMOTE_STATE: str = os.getenv("SLD_REMOTE_STATE", "http://remote-state:8080") + BOT: str = os.getenv("SLD_API_SERVER_USER", "schedule") + BOTC: str = os.getenv("SLD_API_SERVER_PASSWORD", "Schedule1@local") settings = Settings() diff --git a/sld-api-backend/config/celery_config.py b/sld-api-backend/config/celery_config.py index c1df28f6..16cc551d 100644 --- a/sld-api-backend/config/celery_config.py +++ b/sld-api-backend/config/celery_config.py @@ -1,36 +1,36 @@ import os -from celery import Celery +from celery import Celery celery_app = None # Rabbit broker config -BROKER_USER = os.getenv('BROKER_USER', "admin") -BROKER_PASSWD = os.getenv('BROKER_PASSWD', "admin") -BROKER_SERVER = os.getenv('BROKER_SERVER', "rabbit") -BROKER_SERVER_PORT = os.getenv('BROKER_SERVER_PORT', "5672") +BROKER_USER = os.getenv("BROKER_USER", "admin") +BROKER_PASSWD = os.getenv("BROKER_PASSWD", "admin") +BROKER_SERVER = os.getenv("BROKER_SERVER", "rabbit") +BROKER_SERVER_PORT = os.getenv("BROKER_SERVER_PORT", "5672") # Redus backend config -BACKEND_TYPE = os.getenv('BACKEND_TYPE', "redis") -BACKEND_USER = os.getenv('BACKEND_USER', "") -BACKEND_PASSWD = os.getenv('BACKEND_PASSWD', "") -BACKEND_SERVER = os.getenv('BACKEND_SERVER', "redis") -BACKEND_DB = os.getenv('BACKEND_DB', "0") +BACKEND_TYPE = os.getenv("BACKEND_TYPE", "redis") +BACKEND_USER = os.getenv("BACKEND_USER", "") +BACKEND_PASSWD = os.getenv("BACKEND_PASSWD", "") +BACKEND_SERVER = os.getenv("BACKEND_SERVER", "redis") +BACKEND_DB = os.getenv("BACKEND_DB", "0") -if not bool(os.getenv('DOCKER')): # if running example without docker +if not bool(os.getenv("DOCKER")): # if running example without docker celery_app = Celery( "worker", - backend = f"{BACKEND_TYPE}://{BACKEND_USER}:{BACKEND_PASSWD}@{BACKEND_SERVER}/{BACKEND_DB}", - broker = f"amqp://{BROKER_USER}:{BROKER_PASSWD}@{BROKER_SERVER}:{BROKER_SERVER_PORT}//" + backend=f"{BACKEND_TYPE}://{BACKEND_USER}:{BACKEND_PASSWD}@{BACKEND_SERVER}/{BACKEND_DB}", + broker=f"amqp://{BROKER_USER}:{BROKER_PASSWD}@{BROKER_SERVER}:{BROKER_SERVER_PORT}//", ) - celery_app.conf.task_routes={ - "app.worker.celery_worker.test_celery": "api-queue"} + celery_app.conf.task_routes = {"app.worker.celery_worker.test_celery": "api-queue"} else: # running example with docker celery_app = Celery( "worker", - backend = f"{BACKEND_TYPE}://{BACKEND_USER}:{BACKEND_PASSWD}@{BACKEND_SERVER}/{BACKEND_DB}", - broker=f"amqp://{BROKER_USER}:{BROKER_PASSWD}@{BROKER_SERVER}:{BROKER_SERVER_PORT}//" + backend=f"{BACKEND_TYPE}://{BACKEND_USER}:{BACKEND_PASSWD}@{BACKEND_SERVER}/{BACKEND_DB}", + broker=f"amqp://{BROKER_USER}:{BROKER_PASSWD}@{BROKER_SERVER}:{BROKER_SERVER_PORT}//", ) - celery_app.conf.task_routes={ - "app.app.worker.celery_worker.test_celery": "api-queue"} + celery_app.conf.task_routes = { + "app.app.worker.celery_worker.test_celery": "api-queue" + } celery_app.conf.update(task_track_started=True) -celery_app.conf.result_expires = os.getenv('SLD_RESULT_EXPIRE', "259200") +celery_app.conf.result_expires = os.getenv("SLD_RESULT_EXPIRE", "259200") diff --git a/sld-api-backend/config/database.py b/sld-api-backend/config/database.py index 7e700dbf..102d47b3 100644 --- a/sld-api-backend/config/database.py +++ b/sld-api-backend/config/database.py @@ -1,9 +1,12 @@ import os + from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker -SQLALCHEMY_DATABASE_URL = os.getenv('SQLALCHEMY_DATABASE_URL', 'mysql://root:123@db/restapi') +SQLALCHEMY_DATABASE_URL = os.getenv( + "SQLALCHEMY_DATABASE_URL", "mysql://root:123@db/restapi" +) engine = create_engine(SQLALCHEMY_DATABASE_URL, pool_pre_ping=True, pool_recycle=3600) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) diff --git a/sld-api-backend/core/providers/terraform.py b/sld-api-backend/core/providers/terraform.py index c154a7c0..cb8d6cf6 100644 --- a/sld-api-backend/core/providers/terraform.py +++ b/sld-api-backend/core/providers/terraform.py @@ -1,100 +1,112 @@ -import os import json import logging -import subprocess -import jmespath -from os import path +import os +import shutil +from os import listdir, path from os.path import isfile, join -from os import listdir -import hcl -import shutil import ansible_runner -from jinja2 import Template +import hcl +import jmespath from config.api import settings +from jinja2 import Template from security.providers_credentials import secret, unsecret -os.environ['ANSIBLE_NOCOLOR'] = "True" -os.environ['ANSIBLE_DEPRECATION_WARNINGS'] = "False" +os.environ["ANSIBLE_NOCOLOR"] = "True" +os.environ["ANSIBLE_DEPRECATION_WARNINGS"] = "False" class TerraformActions(object): - @staticmethod def binary_download( - stack_name: str, - environment: str, - squad: str, - version: str + stack_name: str, environment: str, squad: str, version: str ) -> dict: - binary = f'{settings.TERRAFORM_BIN_REPO}/{version}/terraform_{version}_linux_amd64.zip' + binary = f"{settings.TERRAFORM_BIN_REPO}/{version}/terraform_{version}_linux_amd64.zip" try: runner_response = ansible_runner.run( rotate_artifacts=1, - private_data_dir=f'/tmp/{stack_name}/{environment}/{squad}', - host_pattern='localhost', - module='file', - module_args=f'path=/tmp/{version} state=directory', + private_data_dir=f"/tmp/{stack_name}/{environment}/{squad}", + host_pattern="localhost", + module="file", + module_args=f"path=/tmp/{version} state=directory", ) runner_response = ansible_runner.run( rotate_artifacts=1, - private_data_dir=f'/tmp/{stack_name}/{environment}/{squad}', - host_pattern='localhost', - module='unarchive', - module_args=f'src={binary} dest=/tmp/{version} remote_src=True', + private_data_dir=f"/tmp/{stack_name}/{environment}/{squad}", + host_pattern="localhost", + module="unarchive", + module_args=f"src={binary} dest=/tmp/{version} remote_src=True", ) logs = [i for i in runner_response.events] binaryDownload_stdout = jmespath.search( - '[*].event_data.res.stdout_lines', logs) - binaryDownload_stderr = jmespath.search( - '[*].event_data.res.msg', logs) + "[*].event_data.res.stdout_lines", logs + ) + binaryDownload_stderr = jmespath.search("[*].event_data.res.msg", logs) rc = runner_response.rc # check result if rc != 0: - return {"command": "binaryDownload", "rc": rc, "stdout": binaryDownload_stderr} - return {"command": "binaryDownload", "rc": rc, "stdout": binaryDownload_stdout} + return { + "command": "binaryDownload", + "rc": rc, + "stdout": binaryDownload_stderr, + } + return { + "command": "binaryDownload", + "rc": rc, + "stdout": binaryDownload_stdout, + } except Exception as err: return {"command": "binaryDownload", "rc": 1, "stdout": str(err)} @staticmethod def git_clone( - git_repo: str, - name: str, - stack_name: str, - environment: str, - squad: str, - branch: str + git_repo: str, + name: str, + stack_name: str, + environment: str, + squad: str, + branch: str, ) -> dict: try: logging.info(f"Download git repo {git_repo} branch {branch}") runner_response = ansible_runner.run( - private_data_dir='/tmp/', - host_pattern='localhost', + private_data_dir="/tmp/", + host_pattern="localhost", verbosity=0, - module='git', - module_args=f'repo={git_repo} dest={stack_name}/{environment}/{squad}/{name} version={branch} force=yes recursive=yes', + module="git", + module_args=f"repo={git_repo} dest={stack_name}/{environment}/{squad}/{name} version={branch} force=yes recursive=yes", ) - path_tfvars = f'/tmp/{stack_name}/{environment}/{squad}/{name}' - tfvars_files = [f for f in listdir(path_tfvars) if f.endswith('.tfvars') and isfile(join(path_tfvars, f))] + path_tfvars = f"/tmp/{stack_name}/{environment}/{squad}/{name}" + tfvars_files = [ + f + for f in listdir(path_tfvars) + if f.endswith(".tfvars") and isfile(join(path_tfvars, f)) + ] logs = [i for i in runner_response.events] - git_stdout = jmespath.search( - '[*].event_data.res.stdout_lines', logs) - git_stderr = jmespath.search('[*].event_data.res.msg', logs) + git_stdout = jmespath.search("[*].event_data.res.stdout_lines", logs) + git_stderr = jmespath.search("[*].event_data.res.msg", logs) rc = runner_response.rc if rc != 0: - return {"command": "git", "rc": rc, "tfvars": tfvars_files, "stdout": git_stderr} - return {"command": "git", "rc": rc, "tfvars": tfvars_files, "stdout": git_stdout} + return { + "command": "git", + "rc": rc, + "tfvars": tfvars_files, + "stdout": git_stderr, + } + return { + "command": "git", + "rc": rc, + "tfvars": tfvars_files, + "stdout": git_stdout, + } except Exception as err: return {"command": "git", "rc": 1, "tfvars": tfvars_files, "stdout": err} @staticmethod def tfstate_render( - stack_name: str, - environment: str, - squad: str, - project_path: str, - name: str) -> dict: - data = ''' + stack_name: str, environment: str, squad: str, project_path: str, name: str + ) -> dict: + data = """ terraform { backend "http" { address = "http://remote-state:8080/terraform_state/{{deploy_state}}" @@ -104,15 +116,16 @@ def tfstate_render( unlock_method = "DELETE" } } - ''' + """ try: tm = Template(data) provider_backend = tm.render( - deploy_state=f'{stack_name}-{squad}-{environment}-{name}') - file_path = f'/tmp/{stack_name}/{environment}/{squad}/{name}/{stack_name}-{name}-{environment}.tf' + deploy_state=f"{stack_name}-{squad}-{environment}-{name}" + ) + file_path = f"/tmp/{stack_name}/{environment}/{squad}/{name}/{stack_name}-{name}-{environment}.tf" if project_path: - file_path = f'/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}/{stack_name}-{name}-{environment}.tf' - with open(file_path, 'w') as tf_state: + file_path = f"/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}/{stack_name}-{name}-{environment}.tf" + with open(file_path, "w") as tf_state: tf_state.write(provider_backend) return {"command": "tfserver", "rc": 0, "stdout": data} except Exception as err: @@ -120,23 +133,25 @@ def tfstate_render( @staticmethod def data_source_render( - stack_name: str, - environment: str, - squad: str, - name: str) -> dict: - data = ''' + stack_name: str, environment: str, squad: str, name: str + ) -> dict: + data = """ data "terraform_remote_state" "generic" { backend = "http" config = { address = "http://remote-state:8080/terraform_state/{{deploy_state}}" } } - ''' + """ try: tm = Template(data) provider_backend = tm.render( - deploy_state=f'{environment}_{stack_name}_{squad}_{name}') - with open(f'/tmp/{stack_name}/{environment}/{squad}/{name}/data_{environment}_{stack_name}_{name}.tf', 'w') as tf_state: + deploy_state=f"{environment}_{stack_name}_{squad}_{name}" + ) + with open( + f"/tmp/{stack_name}/{environment}/{squad}/{name}/data_{environment}_{stack_name}_{name}.tf", + "w", + ) as tf_state: tf_state.write(provider_backend) return {"command": "datasource", "rc": 0, "stdout": data} except Exception as err: @@ -144,54 +159,59 @@ def data_source_render( @staticmethod def tfvars( - stack_name: str, - environment: str, - squad: str, - name: str, - project_path: str, - **kwargs: dict) -> dict: + stack_name: str, + environment: str, + squad: str, + name: str, + project_path: str, + **kwargs: dict, + ) -> dict: try: - file_path = f'/tmp/{stack_name}/{environment}/{squad}/{name}/{stack_name}.tfvars.json' + file_path = f"/tmp/{stack_name}/{environment}/{squad}/{name}/{stack_name}.tfvars.json" if project_path: - file_path = f'/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}/{stack_name}.tfvars.json' - with open(file_path, 'w') as tfvars_json: + file_path = f"/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}/{stack_name}.tfvars.json" + with open(file_path, "w") as tfvars_json: json.dump(kwargs.get("vars"), tfvars_json) return {"command": "tfvars", "rc": 0, "stdout": kwargs.get("vars")} except Exception as err: - return {"command": "tfvars", "rc": 1, "stdout": f'{err}'} + return {"command": "tfvars", "rc": 1, "stdout": f"{err}"} @staticmethod def plan_execute( - stack_name: str, - environment: str, - squad: str, - name: str, - version: str, - variables_file: str = "", - project_path: str = "", - **secreto: dict) -> dict: + stack_name: str, + environment: str, + squad: str, + name: str, + version: str, + variables_file: str = "", + project_path: str = "", + **secreto: dict, + ) -> dict: try: secret(stack_name, environment, squad, name, secreto) - deploy_state=f'{environment}_{stack_name}_{squad}_{name}' + deploy_state = f"{environment}_{stack_name}_{squad}_{name}" # Execute task - variables_files = f'{stack_name}.tfvars.json' if variables_file == "" or variables_file == None else variables_file + variables_files = ( + f"{stack_name}.tfvars.json" + if variables_file == "" or variables_file == None + else variables_file + ) runner_response = ansible_runner.run( - private_data_dir=f'/tmp/{stack_name}/{environment}/{squad}/{name}', - host_pattern='localhost', - module='terraform', - module_args=f'binary_path=/tmp/{version}/terraform ' - f'force_init=True ' - f'project_path=/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path} ' - f'plan_file=/tmp/{stack_name}/{environment}/{squad}/{name}/{stack_name}.tfplan ' - f'variables_files={variables_files} state=planned', + private_data_dir=f"/tmp/{stack_name}/{environment}/{squad}/{name}", + host_pattern="localhost", + module="terraform", + module_args=f"binary_path=/tmp/{version}/terraform " + f"force_init=True " + f"project_path=/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path} " + f"plan_file=/tmp/{stack_name}/{environment}/{squad}/{name}/{stack_name}.tfplan " + f"variables_files={variables_files} state=planned", ) unsecret(stack_name, environment, squad, name, secreto) # Capture events logs = [i for i in runner_response.events] - plan_stdout = jmespath.search( - '[*].event_data.res.stdout_lines', logs) - plan_stderr = jmespath.search('[*].event_data.res.msg', logs) + plan_stdout = jmespath.search("[*].event_data.res.stdout_lines", logs) + plan_stderr = jmespath.search("[*].event_data.res.msg", logs) rc = runner_response.rc # check result if rc != 0: @@ -203,9 +223,9 @@ def plan_execute( "environment": environment, "rc": rc, "tfvars_files": variables_file, - "remote_state": f'http://remote-state:8080/terraform_state/{deploy_state}', - "project_path": f'/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}', - "stdout": plan_stderr + "remote_state": f"http://remote-state:8080/terraform_state/{deploy_state}", + "project_path": f"/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}", + "stdout": plan_stderr, } return { "command": "plan", @@ -215,9 +235,9 @@ def plan_execute( "environment": environment, "rc": rc, "tfvars_files": variables_file, - "project_path": f'/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}', - "remote_state": f'http://remote-state:8080/terraform_state/{deploy_state}', - "stdout": plan_stdout + "project_path": f"/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}", + "remote_state": f"http://remote-state:8080/terraform_state/{deploy_state}", + "stdout": plan_stdout, } except Exception as err: return { @@ -228,43 +248,48 @@ def plan_execute( "environment": environment, "rc": 1, "tfvars_files": variables_file, - "project_path": f'/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}', - "remote_state": f'http://remote-state:8080/terraform_state/{deploy_state}', - "stdout": f'{err}' + "project_path": f"/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}", + "remote_state": f"http://remote-state:8080/terraform_state/{deploy_state}", + "stdout": f"{err}", } @staticmethod def apply_execute( - stack_name: str, - branch: str, - environment: str, - squad: str, - name: str, - version: str, - variables_file: str = "", - project_path: str = "", - **secreto: dict) -> dict: + stack_name: str, + branch: str, + environment: str, + squad: str, + name: str, + version: str, + variables_file: str = "", + project_path: str = "", + **secreto: dict, + ) -> dict: try: secret(stack_name, environment, squad, name, secreto) - deploy_state=f'{environment}_{stack_name}_{squad}_{name}' + deploy_state = f"{environment}_{stack_name}_{squad}_{name}" # Execute task - variables_files = f'{stack_name}.tfvars.json' if variables_file == "" or variables_file == None else variables_file + variables_files = ( + f"{stack_name}.tfvars.json" + if variables_file == "" or variables_file == None + else variables_file + ) runner_response = ansible_runner.run( - private_data_dir=f'/tmp/{stack_name}/{environment}/{squad}/{name}', - host_pattern='localhost', - module='terraform', - module_args=f'binary_path=/tmp/{version}/terraform lock=True force_init=True ' - f'project_path=/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path} ' - f'plan_file=/tmp/{stack_name}/{environment}/{squad}/{name}/{stack_name}.tfplan state=present ' - f'variables_files={variables_files}', + private_data_dir=f"/tmp/{stack_name}/{environment}/{squad}/{name}", + host_pattern="localhost", + module="terraform", + module_args=f"binary_path=/tmp/{version}/terraform lock=True force_init=True " + f"project_path=/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path} " + f"plan_file=/tmp/{stack_name}/{environment}/{squad}/{name}/{stack_name}.tfplan state=present " + f"variables_files={variables_files}", ) unsecret(stack_name, environment, squad, name, secreto) # Capture events apply_logs = [i for i in runner_response.events] apply_stdout = jmespath.search( - '[*].event_data.res.stdout_lines', apply_logs) - apply_stderr = jmespath.search( - '[*].event_data.res.msg', apply_logs) + "[*].event_data.res.stdout_lines", apply_logs + ) + apply_stderr = jmespath.search("[*].event_data.res.msg", apply_logs) rc = runner_response.rc # check result if rc != 0: @@ -277,9 +302,9 @@ def apply_execute( "environment": environment, "rc": rc, "tfvars_files": variables_file, - "project_path": f'/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}', - "remote_state": f'http://remote-state:8080/terraform_state/{deploy_state}', - "stdout": apply_stderr + "project_path": f"/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}", + "remote_state": f"http://remote-state:8080/terraform_state/{deploy_state}", + "stdout": apply_stderr, } return { "command": "apply", @@ -290,9 +315,9 @@ def apply_execute( "environment": environment, "rc": rc, "tfvars_files": variables_file, - "project_path": f'/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}', - "remote_state": f'http://remote-state:8080/terraform_state/{deploy_state}', - "stdout": apply_stdout + "project_path": f"/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}", + "remote_state": f"http://remote-state:8080/terraform_state/{deploy_state}", + "stdout": apply_stdout, } except Exception as err: return { @@ -304,42 +329,47 @@ def apply_execute( "environment": environment, "rc": 1, "tfvars_files": variables_file, - "project_path": f'/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}', - "remote_state": f'http://remote-state:8080/terraform_state/{deploy_state}', - "stdout": f'{err}' + "project_path": f"/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}", + "remote_state": f"http://remote-state:8080/terraform_state/{deploy_state}", + "stdout": f"{err}", } @staticmethod def destroy_execute( - stack_name: str, - branch: str, - environment: str, - squad: str, - name: str, - version: str, - variables_file: str = "", - project_path: str = "", - **secreto: dict) -> dict: + stack_name: str, + branch: str, + environment: str, + squad: str, + name: str, + version: str, + variables_file: str = "", + project_path: str = "", + **secreto: dict, + ) -> dict: try: secret(stack_name, environment, squad, name, secreto) - deploy_state=f'{environment}_{stack_name}_{squad}_{name}' + deploy_state = f"{environment}_{stack_name}_{squad}_{name}" # Execute task - variables_files = f'{stack_name}.tfvars.json' if variables_file == "" or variables_file == None else variables_file + variables_files = ( + f"{stack_name}.tfvars.json" + if variables_file == "" or variables_file == None + else variables_file + ) runner_response = ansible_runner.run( - private_data_dir=f'/tmp/{stack_name}/{environment}/{squad}/{name}', - host_pattern='localhost', - module='terraform', - module_args=f'binary_path=/tmp/{version}/terraform force_init=True ' - f'project_path=/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path} ' - f'variables_files={variables_files} state=absent', + private_data_dir=f"/tmp/{stack_name}/{environment}/{squad}/{name}", + host_pattern="localhost", + module="terraform", + module_args=f"binary_path=/tmp/{version}/terraform force_init=True " + f"project_path=/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path} " + f"variables_files={variables_files} state=absent", ) unsecret(stack_name, environment, squad, name, secreto) # Capture events destroy_logs = [i for i in runner_response.events] destroy_stdout = jmespath.search( - '[*].event_data.res.stdout_lines', destroy_logs) - destroy_stderr = jmespath.search( - '[*].event_data.res.msg', destroy_logs) + "[*].event_data.res.stdout_lines", destroy_logs + ) + destroy_stderr = jmespath.search("[*].event_data.res.msg", destroy_logs) rc = runner_response.rc if rc != 0: return { @@ -351,9 +381,9 @@ def destroy_execute( "environment": environment, "rc": rc, "tfvars_files": variables_file, - "project_path": f'/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}', - "remote_state": f'http://remote-state:8080/terraform_state/{deploy_state}', - "stdout": destroy_stderr + "project_path": f"/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}", + "remote_state": f"http://remote-state:8080/terraform_state/{deploy_state}", + "stdout": destroy_stderr, } return { "command": "destroy", @@ -364,9 +394,9 @@ def destroy_execute( "environment": environment, "rc": rc, "tfvars_files": variables_file, - "project_path": f'/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}', - "remote_state": f'http://remote-state:8080/terraform_state/{deploy_state}', - "stdout": destroy_stdout + "project_path": f"/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}", + "remote_state": f"http://remote-state:8080/terraform_state/{deploy_state}", + "stdout": destroy_stdout, } except Exception as err: return { @@ -378,41 +408,37 @@ def destroy_execute( "environment": environment, "rc": 1, "tfvars_files": variables_file, - "project_path": f'/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}', - "remote_state": f'http://remote-state:8080/terraform_state/{deploy_state}', - "stdout": f'{err}' + "project_path": f"/tmp/{stack_name}/{environment}/{squad}/{name}/{project_path}", + "remote_state": f"http://remote-state:8080/terraform_state/{deploy_state}", + "stdout": f"{err}", } @staticmethod - def output_execute( - stack_name: str, - environment: str, - squad: str, - name: str): + def output_execute(stack_name: str, environment: str, squad: str, name: str): try: import requests - get_path = f'{stack_name}-{squad}-{environment}-{name}' + + get_path = f"{stack_name}-{squad}-{environment}-{name}" response = requests.get( - f'{settings.REMOTE_STATE}/terraform_state/{get_path}') + f"{settings.REMOTE_STATE}/terraform_state/{get_path}" + ) json_data = response.json() - result = json_data.get('outputs') + result = json_data.get("outputs") if not result: - result = jmespath.search('modules[*].outputs', json_data) + result = jmespath.search("modules[*].outputs", json_data) return result except Exception as err: return {"command": "output", "rc": 1, "stdout": err} @staticmethod - def unlock_execute( - stack_name: str, - environment: str, - squad: str, - name: str): + def unlock_execute(stack_name: str, environment: str, squad: str, name: str): try: import requests - get_path = f'{stack_name}-{squad}-{environment}-{name}' + + get_path = f"{stack_name}-{squad}-{environment}-{name}" response = requests.delete( - f'{settings.REMOTE_STATE}/terraform_lock/{get_path}', json={}) + f"{settings.REMOTE_STATE}/terraform_lock/{get_path}", json={} + ) json_data = response.json() result = json_data return result @@ -420,52 +446,47 @@ def unlock_execute( return {"command": "unlock", "rc": 1, "stdout": err} @staticmethod - def show_execute( - stack_name: str, - environment: str, - squad: str, - name: str): + def show_execute(stack_name: str, environment: str, squad: str, name: str): try: import requests - get_path = f'{stack_name}-{squad}-{environment}-{name}' + + get_path = f"{stack_name}-{squad}-{environment}-{name}" response = requests.get( - f'{settings.REMOTE_STATE}/terraform_state/{get_path}') + f"{settings.REMOTE_STATE}/terraform_state/{get_path}" + ) json_data = response.json() return json_data except Exception as err: return {"command": "show", "rc": 1, "stdout": err} @staticmethod - def get_vars_tfvars( - stack_name: str, - environment: str, - squad: str, - name: str): + def get_vars_tfvars(stack_name: str, environment: str, squad: str, name: str): if path.exists( - f"/tmp/{ stack_name }/{environment}/{squad}/{name}/{stack_name}.tfvars.json"): - with open(f"/tmp/{ stack_name }/{environment}/{squad}/{name}/{stack_name}.tfvars.json", "r") as tfvars: + f"/tmp/{ stack_name }/{environment}/{squad}/{name}/{stack_name}.tfvars.json" + ): + with open( + f"/tmp/{ stack_name }/{environment}/{squad}/{name}/{stack_name}.tfvars.json", + "r", + ) as tfvars: tf = tfvars.read() return json.loads(tf) else: return { "action": f"terraform.tfvars not exist in module {stack_name}", - "rc": 1} + "rc": 1, + } @staticmethod - def get_vars_list( - stack_name: str, - environment: str, - squad: str, - name: str) -> list: + def get_vars_list(stack_name: str, environment: str, squad: str, name: str) -> list: try: file_hcl = f"/tmp/{ stack_name }/{environment}/{squad}/{name}/variables.tf" - with open(file_hcl, 'r') as fp: + with open(file_hcl, "r") as fp: obj = hcl.load(fp) - if obj.get('variable'): - lista = [i for i in obj.get('variable')] + if obj.get("variable"): + lista = [i for i in obj.get("variable")] return {"command": "get_vars_list", "rc": 0, "stdout": lista} else: - error_msg = 'Variable file is empty, not iterable' + error_msg = "Variable file is empty, not iterable" return {"command": "get_vars_list", "rc": 1, "stdout": error_msg} except IOError: error_msg = "Variable file not accessible" @@ -474,19 +495,15 @@ def get_vars_list( return {"command": "get_vars_list", "rc": 1, "stdout": err} @staticmethod - def get_vars_json( - stack_name: str, - environment: str, - squad: str, - name: str) -> dict: + def get_vars_json(stack_name: str, environment: str, squad: str, name: str) -> dict: try: file_hcl = f"/tmp/{stack_name}/{environment}/{squad}/{name}/variables.tf" - with open(file_hcl, 'r') as fp: + with open(file_hcl, "r") as fp: obj = hcl.load(fp) - if obj.get('variable'): + if obj.get("variable"): return {"command": "get_vars_json", "rc": 0, "stdout": json.dumps(obj)} else: - error_msg = 'Variable file is empty, not iterable' + error_msg = "Variable file is empty, not iterable" return {"command": "get_vars_json", "rc": 1, "stdout": error_msg} except IOError: error_msg = "Variable file not accessible" diff --git a/sld-api-backend/crud/activityLogs.py b/sld-api-backend/crud/activityLogs.py index cf8f9718..d36342a9 100644 --- a/sld-api-backend/crud/activityLogs.py +++ b/sld-api-backend/crud/activityLogs.py @@ -1,19 +1,16 @@ -from sqlalchemy.orm import Session import datetime import db.models as models +from sqlalchemy.orm import Session -def create_activity_log( - db: Session, - username: str, - squad: str, - action: str): +def create_activity_log(db: Session, username: str, squad: str, action: str): db_activity = models.ActivityLogs( username=username, squad=squad, created_at=datetime.datetime.now(), - action=action) + action=action, + ) try: db.add(db_activity) db.commit() @@ -26,7 +23,12 @@ def create_activity_log( def get_all_activity(db: Session, skip: int = 0, limit: int = 100): try: db_query = db.query(models.ActivityLogs) - return db_query.order_by(models.ActivityLogs.created_at.desc()).offset(skip).limit(limit).all() + return ( + db_query.order_by(models.ActivityLogs.created_at.desc()) + .offset(skip) + .limit(limit) + .all() + ) except Exception as err: raise err @@ -34,11 +36,18 @@ def get_all_activity(db: Session, skip: int = 0, limit: int = 100): def get_all_activity_by_squad(db: Session, squad: str, skip: int = 0, limit: int = 100): try: from sqlalchemy import func - result=[] + + result = [] for i in squad: - a=f'["{i}"]' - result.extend(db.query(models.ActivityLogs).filter(func.json_contains( - models.ActivityLogs.squad, a) == 1).order_by(models.ActivityLogs.created_at.desc()).offset(skip).limit(limit).all()) + a = f'["{i}"]' + result.extend( + db.query(models.ActivityLogs) + .filter(func.json_contains(models.ActivityLogs.squad, a) == 1) + .order_by(models.ActivityLogs.created_at.desc()) + .offset(skip) + .limit(limit) + .all() + ) return set(result) except Exception as err: raise err @@ -46,15 +55,22 @@ def get_all_activity_by_squad(db: Session, squad: str, skip: int = 0, limit: int def get_activity_by_username(db: Session, username: int): try: - return db.query( - models.ActivityLogs).filter( - models.ActivityLogs.username == username).all() + return ( + db.query(models.ActivityLogs) + .filter(models.ActivityLogs.username == username) + .all() + ) except Exception as err: raise err def get_activity_by_username_squad(db: Session, username: int, squad: str): try: - return db.query(models.ActivityLogs).filter(models.ActivityLogs.username == username).filter(models.ActivityLogs.squad == squad).all() + return ( + db.query(models.ActivityLogs) + .filter(models.ActivityLogs.username == username) + .filter(models.ActivityLogs.squad == squad) + .all() + ) except Exception as err: raise err diff --git a/sld-api-backend/crud/aws.py b/sld-api-backend/crud/aws.py index 0b6e264c..b2d53ff2 100644 --- a/sld-api-backend/crud/aws.py +++ b/sld-api-backend/crud/aws.py @@ -1,10 +1,9 @@ -from sqlalchemy.orm import Session -from sqlalchemy import func import datetime -from security.vault import vault_encrypt, vault_decrypt import db.models as models import schemas.schemas as schemas +from security.vault import vault_decrypt, vault_encrypt +from sqlalchemy.orm import Session @vault_encrypt @@ -26,15 +25,17 @@ def decrypt(secreto): def create_aws_profile(db: Session, aws: schemas.AwsAsumeProfile): encrypt_access_key_id = encrypt(aws.access_key_id) encrypt_secret_access_key = encrypt(aws.secret_access_key) - db_aws = models.Aws_provider(access_key_id=encrypt_access_key_id, - secret_access_key=encrypt_secret_access_key, - environment=aws.environment, - default_region=aws.default_region, - profile_name=aws.profile_name, - role_arn=aws.role_arn, - source_profile=aws.source_profile, - created_at=datetime.datetime.now(), - squad=aws.squad) + db_aws = models.Aws_provider( + access_key_id=encrypt_access_key_id, + secret_access_key=encrypt_secret_access_key, + environment=aws.environment, + default_region=aws.default_region, + profile_name=aws.profile_name, + role_arn=aws.role_arn, + source_profile=aws.source_profile, + created_at=datetime.datetime.now(), + squad=aws.squad, + ) check_None = [None, "string"] if db_aws.role_arn in check_None: db_aws.role_arn = "" @@ -52,18 +53,42 @@ def create_aws_profile(db: Session, aws: schemas.AwsAsumeProfile): def get_credentials_aws_profile(db: Session, environment: str, squad: str): - get_access_key = db.query(models.Aws_provider.access_key_id).filter( - models.Aws_provider.environment == environment).filter(models.Aws_provider.squad == squad).first() - get_secret_access_key = db.query(models.Aws_provider.secret_access_key).filter( - models.Aws_provider.environment == environment).filter(models.Aws_provider.squad == squad).first() - default_region = db.query(models.Aws_provider.default_region).filter( - models.Aws_provider.environment == environment).filter(models.Aws_provider.squad == squad).first() - profile_name = db.query(models.Aws_provider.profile_name).filter( - models.Aws_provider.environment == environment).filter(models.Aws_provider.squad == squad).first() - role_arn = db.query(models.Aws_provider.role_arn).filter( - models.Aws_provider.environment == environment).filter(models.Aws_provider.squad == squad).first() - source_profile = db.query(models.Aws_provider.source_profile).filter( - models.Aws_provider.environment == environment).filter(models.Aws_provider.squad == squad).first() + get_access_key = ( + db.query(models.Aws_provider.access_key_id) + .filter(models.Aws_provider.environment == environment) + .filter(models.Aws_provider.squad == squad) + .first() + ) + get_secret_access_key = ( + db.query(models.Aws_provider.secret_access_key) + .filter(models.Aws_provider.environment == environment) + .filter(models.Aws_provider.squad == squad) + .first() + ) + default_region = ( + db.query(models.Aws_provider.default_region) + .filter(models.Aws_provider.environment == environment) + .filter(models.Aws_provider.squad == squad) + .first() + ) + profile_name = ( + db.query(models.Aws_provider.profile_name) + .filter(models.Aws_provider.environment == environment) + .filter(models.Aws_provider.squad == squad) + .first() + ) + role_arn = ( + db.query(models.Aws_provider.role_arn) + .filter(models.Aws_provider.environment == environment) + .filter(models.Aws_provider.squad == squad) + .first() + ) + source_profile = ( + db.query(models.Aws_provider.source_profile) + .filter(models.Aws_provider.environment == environment) + .filter(models.Aws_provider.squad == squad) + .first() + ) try: return { "access_key": decrypt(get_access_key[0]), @@ -71,7 +96,7 @@ def get_credentials_aws_profile(db: Session, environment: str, squad: str): "default_region": default_region[0], "profile_name": profile_name[0], "role_arn": role_arn[0], - "source_profile": source_profile[0] + "source_profile": source_profile[0], } except Exception as err: raise err @@ -80,11 +105,19 @@ def get_credentials_aws_profile(db: Session, environment: str, squad: str): def get_squad_aws_profile(db: Session, squad: str, environment: str): try: if environment != None: - return db.query(models.Aws_provider).filter(models.Aws_provider.squad == squad).filter( - models.Aws_provider.environment == environment).first() + return ( + db.query(models.Aws_provider) + .filter(models.Aws_provider.squad == squad) + .filter(models.Aws_provider.environment == environment) + .first() + ) result = [] for i in squad: - result.extend(db.query(models.Aws_provider).filter(models.Aws_provider.squad == i).all()) + result.extend( + db.query(models.Aws_provider) + .filter(models.Aws_provider.squad == i) + .all() + ) return set(result) except Exception as err: raise err @@ -99,7 +132,8 @@ def get_all_aws_profile(db: Session): def delete_aws_profile_by_id(db: Session, aws_profile_id: int): db.query(models.Aws_provider).filter( - models.Aws_provider.id == aws_profile_id).delete() + models.Aws_provider.id == aws_profile_id + ).delete() try: db.commit() return {aws_profile_id: "deleted", "aws_profile_id": aws_profile_id} diff --git a/sld-api-backend/crud/azure.py b/sld-api-backend/crud/azure.py index d9b4e346..f5397038 100644 --- a/sld-api-backend/crud/azure.py +++ b/sld-api-backend/crud/azure.py @@ -1,10 +1,10 @@ -from sqlalchemy.orm import Session import datetime -from security.vault import vault_encrypt, vault_decrypt import db.models as models import schemas.schemas as schemas +from security.vault import vault_decrypt, vault_encrypt from sqlalchemy import exc +from sqlalchemy.orm import Session @vault_encrypt @@ -27,40 +27,58 @@ def create_azure_profile(db: Session, azure: schemas.AzureBase): encrypt_client_id = encrypt(azure.client_id) encrypt_client_secret = encrypt(azure.client_secret) - db_azure = models.Azure_provider(client_id=encrypt_client_id, - client_secret=encrypt_client_secret, - subscription_id=azure.subscription_id, - environment=azure.environment, - tenant_id=azure.tenant_id, - created_at=datetime.datetime.now(), - squad=azure.squad) + db_azure = models.Azure_provider( + client_id=encrypt_client_id, + client_secret=encrypt_client_secret, + subscription_id=azure.subscription_id, + environment=azure.environment, + tenant_id=azure.tenant_id, + created_at=datetime.datetime.now(), + squad=azure.squad, + ) try: db.add(db_azure) db.commit() db.refresh(db_azure) return db_azure except exc.IntegrityError as err: - raise ValueError(str(err.__dict__['orig'])) + raise ValueError(str(err.__dict__["orig"])) except Exception as err: raise err def get_credentials_azure_profile(db: Session, environment: str, squad: str): - get_client_id = db.query(models.Azure_provider.client_id).filter(models.Azure_provider.environment == environment).filter(models.Azure_provider.squad == squad).first() - get_client_secret = db.query(models.Azure_provider.client_secret).filter( - models.Azure_provider.environment == environment).filter(models.Azure_provider.squad == squad).first() - subscription_id = db.query(models.Azure_provider.subscription_id).filter( - models.Azure_provider.environment == environment).filter(models.Azure_provider.squad == squad).first() - tenant_id = db.query(models.Azure_provider.tenant_id).filter( - models.Azure_provider.environment == environment).filter(models.Azure_provider.squad == squad).first() + get_client_id = ( + db.query(models.Azure_provider.client_id) + .filter(models.Azure_provider.environment == environment) + .filter(models.Azure_provider.squad == squad) + .first() + ) + get_client_secret = ( + db.query(models.Azure_provider.client_secret) + .filter(models.Azure_provider.environment == environment) + .filter(models.Azure_provider.squad == squad) + .first() + ) + subscription_id = ( + db.query(models.Azure_provider.subscription_id) + .filter(models.Azure_provider.environment == environment) + .filter(models.Azure_provider.squad == squad) + .first() + ) + tenant_id = ( + db.query(models.Azure_provider.tenant_id) + .filter(models.Azure_provider.environment == environment) + .filter(models.Azure_provider.squad == squad) + .first() + ) try: return { - "client_id": decrypt( - get_client_id[0]), - "client_secret": decrypt( - get_client_secret[0]), + "client_id": decrypt(get_client_id[0]), + "client_secret": decrypt(get_client_secret[0]), "subscription_id": subscription_id[0], - "tenant_id": tenant_id[0]} + "tenant_id": tenant_id[0], + } except Exception as err: raise err @@ -68,12 +86,19 @@ def get_credentials_azure_profile(db: Session, environment: str, squad: str): def get_squad_azure_profile(db: Session, squad: str, environment: str): try: if environment != None: - return db.query(models.Azure_provider).filter( - models.Azure_provider.squad == squad).filter( - models.Azure_provider.environment == environment).first() + return ( + db.query(models.Azure_provider) + .filter(models.Azure_provider.squad == squad) + .filter(models.Azure_provider.environment == environment) + .first() + ) result = [] for i in squad: - result.extend(db.query(models.Azure_provider).filter(models.Azure_provider.squad == i).all()) + result.extend( + db.query(models.Azure_provider) + .filter(models.Azure_provider.squad == i) + .all() + ) return set(result) except Exception as err: raise err @@ -88,10 +113,10 @@ def get_all_azure_profile(db: Session): def delete_azure_profile_by_id(db: Session, azure_profile_id: int): db.query(models.Azure_provider).filter( - models.Azure_provider.id == azure_profile_id).delete() + models.Azure_provider.id == azure_profile_id + ).delete() try: db.commit() - return {azure_profile_id: "deleted", - "azure_profile_id": azure_profile_id} + return {azure_profile_id: "deleted", "azure_profile_id": azure_profile_id} except Exception as err: raise err diff --git a/sld-api-backend/crud/deploys.py b/sld-api-backend/crud/deploys.py index 74fa8e6f..c72eda0c 100644 --- a/sld-api-backend/crud/deploys.py +++ b/sld-api-backend/crud/deploys.py @@ -1,21 +1,20 @@ import datetime -from sqlalchemy.orm import Session -from sqlalchemy import func - import db.models as models import schemas.schemas as schemas +from sqlalchemy.orm import Session def create_new_deploy( - db: Session, - deploy: schemas.DeployCreate, - stack_branch: str, - action: str, - user_id: int, - squad: str, - task_id: str, - username: str): + db: Session, + deploy: schemas.DeployCreate, + stack_branch: str, + action: str, + user_id: int, + squad: str, + task_id: str, + username: str, +): db_deploy = models.Deploy( name=deploy.name, stack_name=deploy.stack_name, @@ -43,20 +42,20 @@ def create_new_deploy( def update_deploy( - db: Session, - deploy_id: int, - action: str, - username: str, - user_id: int, - task_id: str, - start_time: str, - destroy_time: str, - stack_branch: str, - tfvar_file: str, - project_path: str, - variables: dict): - db_deploy = db.query(models.Deploy).filter( - models.Deploy.id == deploy_id).first() + db: Session, + deploy_id: int, + action: str, + username: str, + user_id: int, + task_id: str, + start_time: str, + destroy_time: str, + stack_branch: str, + tfvar_file: str, + project_path: str, + variables: dict, +): + db_deploy = db.query(models.Deploy).filter(models.Deploy.id == deploy_id).first() db_deploy.action = action db_deploy.task_id = task_id @@ -81,14 +80,9 @@ def update_deploy( raise err -def update_plan( - db: Session, - deploy_id: int, - action: str, - task_id: str): +def update_plan(db: Session, deploy_id: int, action: str, task_id: str): - db_deploy = db.query(models.Deploy).filter( - models.Deploy.id == deploy_id).first() + db_deploy = db.query(models.Deploy).filter(models.Deploy.id == deploy_id).first() db_deploy.action = action db_deploy.task_id = task_id @@ -101,14 +95,9 @@ def update_plan( raise err -def update_schedule( - db: Session, - deploy_id: int, - start_time: str, - destroy_time: str): +def update_schedule(db: Session, deploy_id: int, start_time: str, destroy_time: str): - db_deploy = db.query(models.Deploy).filter( - models.Deploy.id == deploy_id).first() + db_deploy = db.query(models.Deploy).filter(models.Deploy.id == deploy_id).first() db_deploy.start_time = start_time db_deploy.destroy_time = destroy_time @@ -122,10 +111,9 @@ def update_schedule( def delete_deploy_by_id(db: Session, deploy_id: int, squad: str): - db.query( - models.Deploy).filter( - models.Deploy.id == deploy_id).filter( - models.Deploy.squad == squad).delete() + db.query(models.Deploy).filter(models.Deploy.id == deploy_id).filter( + models.Deploy.squad == squad + ).delete() try: db.commit() return {models.Deploy.id: "deleted", "Deploy_id": deploy_id} @@ -149,21 +137,27 @@ def get_deploy_by_name(db: Session, deploy_name: str): def get_deploy_by_id_squad(db: Session, deploy_id: int, squad: str): try: - return db.query( - models.Deploy).filter( - models.Deploy.id == deploy_id).filter( - models.Deploy.squad == squad).first() + return ( + db.query(models.Deploy) + .filter(models.Deploy.id == deploy_id) + .filter(models.Deploy.squad == squad) + .first() + ) except Exception as err: raise err -def get_deploy_by_name_squad(db: Session, deploy_name: str, squad: str, environment: str): +def get_deploy_by_name_squad( + db: Session, deploy_name: str, squad: str, environment: str +): try: - return db.query( - models.Deploy).filter( - models.Deploy.name == deploy_name).filter( - models.Deploy.squad == squad).filter( - models.Deploy.environment == environment).first() + return ( + db.query(models.Deploy) + .filter(models.Deploy.name == deploy_name) + .filter(models.Deploy.squad == squad) + .filter(models.Deploy.environment == environment) + .first() + ) except Exception as err: raise err @@ -179,7 +173,9 @@ def get_all_deploys_by_squad(db: Session, squad: str, skip: int = 0, limit: int try: result = [] for i in squad: - result.extend(db.query(models.Deploy).filter(models.Deploy.squad == i).all()) + result.extend( + db.query(models.Deploy).filter(models.Deploy.squad == i).all() + ) return set(result) except Exception as err: raise err diff --git a/sld-api-backend/crud/gcp.py b/sld-api-backend/crud/gcp.py index d544aeb7..5349b414 100644 --- a/sld-api-backend/crud/gcp.py +++ b/sld-api-backend/crud/gcp.py @@ -1,9 +1,9 @@ -from sqlalchemy.orm import Session import datetime -from security.vault import vault_encrypt, vault_decrypt import db.models as models +from security.vault import vault_decrypt, vault_encrypt from sqlalchemy import exc +from sqlalchemy.orm import Session @vault_encrypt @@ -23,32 +23,35 @@ def decrypt(secreto): def create_gcloud_profile( - db: Session, - squad: str, - environment: str, - gcloud_keyfile_json: dict): + db: Session, squad: str, environment: str, gcloud_keyfile_json: dict +): encrypt_glcoud_keyfile_json = encrypt(str(gcloud_keyfile_json)) db_gcloud = models.Gcloud_provider( gcloud_keyfile_json=encrypt_glcoud_keyfile_json, environment=environment, created_at=datetime.datetime.now(), - squad=squad) + squad=squad, + ) try: db.add(db_gcloud) db.commit() db.refresh(db_gcloud) return db_gcloud except exc.IntegrityError as err: - raise ValueError(str(err.__dict__['orig'])) + raise ValueError(str(err.__dict__["orig"])) except Exception as err: raise err def get_credentials_gcloud_profile(db: Session, environment: str, squad: str): try: - get_gcloud_keyfile = db.query(models.Gcloud_provider.gcloud_keyfile_json).filter( - models.Gcloud_provider.environment == environment).filter(models.Gcloud_provider.squad == squad).first() + get_gcloud_keyfile = ( + db.query(models.Gcloud_provider.gcloud_keyfile_json) + .filter(models.Gcloud_provider.environment == environment) + .filter(models.Gcloud_provider.squad == squad) + .first() + ) return {"gcloud_keyfile_json": decrypt(get_gcloud_keyfile[0])} except Exception as err: raise err @@ -57,12 +60,19 @@ def get_credentials_gcloud_profile(db: Session, environment: str, squad: str): def get_squad_gcloud_profile(db: Session, squad: str, environment: str): try: if environment != None: - return db.query(models.Gcloud_provider).filter( - models.Gcloud_provider.squad == squad).filter( - models.Gcloud_provider.environment == environment).first() + return ( + db.query(models.Gcloud_provider) + .filter(models.Gcloud_provider.squad == squad) + .filter(models.Gcloud_provider.environment == environment) + .first() + ) result = [] for i in squad: - result.extend(db.query(models.Gcloud_provider).filter(models.Gcloud_provider.squad == i).all()) + result.extend( + db.query(models.Gcloud_provider) + .filter(models.Gcloud_provider.squad == i) + .all() + ) return set(result) except Exception as err: raise err @@ -77,10 +87,10 @@ def get_all_gcloud_profile(db: Session): def delete_gcloud_profile_by_id(db: Session, gcloud_profile_id: int): db.query(models.Gcloud_provider).filter( - models.Gcloud_provider.id == gcloud_profile_id).delete() + models.Gcloud_provider.id == gcloud_profile_id + ).delete() try: db.commit() - return {gcloud_profile_id: "deleted", - "gcloud_profile_id": gcloud_profile_id} + return {gcloud_profile_id: "deleted", "gcloud_profile_id": gcloud_profile_id} except Exception as err: raise err diff --git a/sld-api-backend/crud/stacks.py b/sld-api-backend/crud/stacks.py index d84dde71..b34d1b24 100644 --- a/sld-api-backend/crud/stacks.py +++ b/sld-api-backend/crud/stacks.py @@ -1,19 +1,19 @@ -from sqlalchemy.orm import Session -from sqlalchemy import func import datetime import db.models as models import schemas.schemas as schemas +from sqlalchemy.orm import Session def create_new_stack( - db: Session, - stack: schemas.StackCreate, - user_id: int, - task_id: str, - var_json: str, - var_list: str, - squad_access: str): + db: Session, + stack: schemas.StackCreate, + user_id: int, + task_id: str, + var_json: str, + var_list: str, + squad_access: str, +): db_stack = models.Stack( stack_name=stack.stack_name, git_repo=stack.git_repo, @@ -25,7 +25,8 @@ def create_new_stack( var_json=var_json, var_list=var_list, squad_access=squad_access, - task_id=task_id) + task_id=task_id, + ) try: db.add(db_stack) db.commit() @@ -36,16 +37,16 @@ def create_new_stack( def update_stack( - db: Session, - stack: schemas.StackCreate, - stack_id: int, - user_id: int, - task_id: str, - var_json: str, - var_list: str, - squad_access: str): - db_stack = db.query(models.Stack).filter( - models.Stack.id == stack_id).first() + db: Session, + stack: schemas.StackCreate, + stack_id: int, + user_id: int, + task_id: str, + var_json: str, + var_list: str, + squad_access: str, +): + db_stack = db.query(models.Stack).filter(models.Stack.id == stack_id).first() db_stack.user_id = user_id db_stack.task_id = task_id @@ -74,14 +75,27 @@ def update_stack( raise err -def get_all_stacks_by_squad(db: Session, squad_access: str, skip: int = 0, limit: int = 100): +def get_all_stacks_by_squad( + db: Session, squad_access: str, skip: int = 0, limit: int = 100 +): try: - filter_all = db.query(models.Stack).filter(models.Stack.squad_access.contains("*")).offset(skip).limit(limit).all() + filter_all = ( + db.query(models.Stack) + .filter(models.Stack.squad_access.contains("*")) + .offset(skip) + .limit(limit) + .all() + ) from sqlalchemy import func + result = [] for i in squad_access: a = f'["{i}"]' - result.extend(db.query(models.Stack).filter(func.json_contains(models.Stack.squad_access, a) == 1).all()) + result.extend( + db.query(models.Stack) + .filter(func.json_contains(models.Stack.squad_access, a) == 1) + .all() + ) merge_query = result + filter_all return set(merge_query) except Exception as err: @@ -97,9 +111,7 @@ def get_all_stacks(db: Session, squad_access: str, skip: int = 0, limit: int = 1 def get_stack_by_id(db: Session, stack_id: int): try: - return db.query( - models.Stack).filter( - models.Stack.id == stack_id).first() + return db.query(models.Stack).filter(models.Stack.id == stack_id).first() except Exception as err: raise err @@ -115,16 +127,15 @@ def delete_stack_by_id(db: Session, stack_id: int): def get_stack_by_name(db: Session, stack_name: str): try: - return db.query( - models.Stack).filter( - models.Stack.stack_name == stack_name).first() + return ( + db.query(models.Stack).filter(models.Stack.stack_name == stack_name).first() + ) except Exception as err: raise err def delete_stack_by_name(db: Session, stack_name: str): - db.query(models.Stack).filter( - models.Stack.stack_name == stack_name).delete() + db.query(models.Stack).filter(models.Stack.stack_name == stack_name).delete() try: db.commit() return {"result": "deleted", "stack_name": stack_name} diff --git a/sld-api-backend/crud/tasks.py b/sld-api-backend/crud/tasks.py index 511b1cc4..c18717ad 100644 --- a/sld-api-backend/crud/tasks.py +++ b/sld-api-backend/crud/tasks.py @@ -1,18 +1,19 @@ -from sqlalchemy.orm import Session import datetime import db.models as models +from sqlalchemy.orm import Session def create_task( - db: Session, - task_id: str, - task_name: str, - user_id: int, - deploy_id: int, - username: str, - squad: str, - action: str): + db: Session, + task_id: str, + task_name: str, + user_id: int, + deploy_id: int, + username: str, + squad: str, + action: str, +): db_task = models.Tasks( task_id=task_id, task_name=task_name, @@ -21,7 +22,8 @@ def create_task( username=username, squad=squad, created_at=datetime.datetime.now(), - action=action) + action=action, + ) try: db.add(db_task) db.commit() @@ -35,16 +37,28 @@ def get_all_tasks(db: Session, skip: int = 0, limit: int = 100): try: db_query = db.query(models.Tasks) - return db_query.order_by(models.Tasks.created_at.desc()).offset(skip).limit(limit).all() + return ( + db_query.order_by(models.Tasks.created_at.desc()) + .offset(skip) + .limit(limit) + .all() + ) except Exception as err: raise err + def get_all_tasks_by_squad(db: Session, squad: str, skip: int = 0, limit: int = 100): try: - from sqlalchemy import func result = [] for i in squad: - result.extend(db.query(models.Tasks).filter(models.Tasks.squad == i).order_by(models.Tasks.created_at.desc()).offset(skip).limit(limit).all()) + result.extend( + db.query(models.Tasks) + .filter(models.Tasks.squad == i) + .order_by(models.Tasks.created_at.desc()) + .offset(skip) + .limit(limit) + .all() + ) return result except Exception as err: raise err @@ -52,8 +66,6 @@ def get_all_tasks_by_squad(db: Session, squad: str, skip: int = 0, limit: int = def get_tasks_by_deploy_id(db: Session, deploy_id: int): try: - return db.query( - models.Tasks).filter( - models.Tasks.deploy_id == deploy_id).all() + return db.query(models.Tasks).filter(models.Tasks.deploy_id == deploy_id).all() except Exception as err: raise err diff --git a/sld-api-backend/crud/user.py b/sld-api-backend/crud/user.py index e3ab3086..eb551e9e 100644 --- a/sld-api-backend/crud/user.py +++ b/sld-api-backend/crud/user.py @@ -1,15 +1,15 @@ -import bcrypt -import sys -from sqlalchemy.orm import Session -from sqlalchemy import exc import datetime +import logging +import sys -from security.vault import vault_encrypt, vault_decrypt -from security.tokens import get_password_hash -from config.api import settings +import bcrypt import db.models as models import schemas.schemas as schemas -import logging +from config.api import settings +from security.tokens import get_password_hash +from security.vault import vault_decrypt, vault_encrypt +from sqlalchemy import exc +from sqlalchemy.orm import Session logging.getLogger("uvicorn.error").propagate = False logging.basicConfig(stream=sys.stdout, level=logging.INFO) @@ -59,9 +59,7 @@ def is_master(db: Session, user: schemas.UserCreate) -> bool: def get_user_by_username(db: Session, username: str): try: - return db.query( - models.User).filter( - models.User.username == username).first() + return db.query(models.User).filter(models.User.username == username).first() except Exception as err: raise err @@ -75,16 +73,24 @@ def get_user_by_id(db: Session, id: int): def get_user_by_username_squad(db: Session, username: str): try: - return db.query( - models.User).filter( - models.User.username == username).filter(models.User.squad == squad).first() + return ( + db.query(models.User) + .filter(models.User.username == username) + .filter(models.User.squad == squad) + .first() + ) except Exception as err: raise err def get_user_by_id_squad(db: Session, id: int): try: - return db.query(models.User).filter(models.User.id == id).filter(models.User.squad == squad).first() + return ( + db.query(models.User) + .filter(models.User.id == id) + .filter(models.User.squad == squad) + .first() + ) except Exception as err: raise err @@ -92,10 +98,15 @@ def get_user_by_id_squad(db: Session, id: int): def get_users_by_squad(db: Session, squad: str, skip: int = 0, limit: int = 100): try: from sqlalchemy import func + result = [] for i in squad: a = f'["{i}"]' - result.extend(db.query(models.User).filter(func.json_contains(models.User.squad, a) == 1).all()) + result.extend( + db.query(models.User) + .filter(func.json_contains(models.User.squad, a) == 1) + .all() + ) return set(result) except Exception as err: raise err @@ -112,12 +123,12 @@ def create_init_user(db: Session, password: str): db_user_schedule = models.User( username=settings.BOT, fullname="Bot sld-schedule service", - email=f'{settings.BOT}@internal.local', + email=f"{settings.BOT}@internal.local", squad=["*"], role=["yoda", "R2-D2"], is_active=True, created_at=datetime.datetime.now(), - password=hashing_passwd(settings.BOTC) + password=hashing_passwd(settings.BOTC), ) db_user = models.User( @@ -128,7 +139,7 @@ def create_init_user(db: Session, password: str): role=["yoda"], is_active=True, created_at=datetime.datetime.now(), - password=hashing_passwd(password) + password=hashing_passwd(password), ) try: db.add(db_user_schedule) @@ -151,14 +162,13 @@ def create_user(db: Session, user: schemas.UserCreate): db.refresh(db_user) return db_user except exc.IntegrityError as err: - raise ValueError(str(err.__dict__['orig'])) + raise ValueError(str(err.__dict__["orig"])) except Exception as err: raise err def update_user(db: Session, user_id: int, user: schemas.UserUpdate): - db_user = db.query(models.User).filter( - models.User.id == user_id).first() + db_user = db.query(models.User).filter(models.User.id == user_id).first() db_user.updated_at = datetime.datetime.now() check_None = [None, "", "string"] if user.password not in check_None: @@ -185,8 +195,7 @@ def update_user(db: Session, user_id: int, user: schemas.UserUpdate): def password_reset(db: Session, user_id: int, password: schemas.PasswordReset): - db_user = db.query(models.User).filter( - models.User.id == user_id).first() + db_user = db.query(models.User).filter(models.User.id == user_id).first() db_user.updated_at = datetime.datetime.now() check_None = [None, "", "string"] @@ -202,8 +211,7 @@ def password_reset(db: Session, user_id: int, password: schemas.PasswordReset): def delete_user_by_id(db: Session, id: int): - db.query(models.User).filter( - models.User.id == id).delete() + db.query(models.User).filter(models.User.id == id).delete() try: db.commit() return {id: "deleted"} @@ -212,8 +220,7 @@ def delete_user_by_id(db: Session, id: int): def delete_user_by_name(db: Session, username: str): - db.query(models.User).filter( - models.User.username == username).delete() + db.query(models.User).filter(models.User.username == username).delete() try: db.commit() return {username: "deleted"} @@ -222,11 +229,10 @@ def delete_user_by_name(db: Session, username: str): def check_username_password(db: Session, user: schemas.UserAuthenticate): - db_user_info: models.User = get_user_by_username( - db, username=user.username) + db_user_info: models.User = get_user_by_username(db, username=user.username) try: return bcrypt.checkpw( - user.password.encode('utf-8'), - db_user_info.password.encode('utf-8')) + user.password.encode("utf-8"), db_user_info.password.encode("utf-8") + ) except Exception as err: raise err diff --git a/sld-api-backend/db/models.py b/sld-api-backend/db/models.py index 2b69eb50..3a4491b4 100644 --- a/sld-api-backend/db/models.py +++ b/sld-api-backend/db/models.py @@ -1,7 +1,9 @@ -from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey, Text, UniqueConstraint, JSON +import datetime + from config.database import Base +from sqlalchemy import (JSON, Boolean, Column, DateTime, ForeignKey, Integer, + String, Text, UniqueConstraint) from sqlalchemy.orm import relationship -import datetime class User(Base): @@ -32,7 +34,7 @@ class Stack(Base): tf_version = Column(String(30)) created_at = Column(DateTime, default=datetime.datetime.now()) description = Column(Text()) - user_id = Column(Integer, ForeignKey('users.id')) + user_id = Column(Integer, ForeignKey("users.id")) owner = relationship("User", back_populates="stacks") @@ -48,7 +50,7 @@ class Aws_provider(Base): role_arn = Column(String(200), nullable=True) source_profile = Column(String(200), nullable=True) created_at = Column(DateTime, default=datetime.datetime.now()) - __table_args__ = (UniqueConstraint('squad', 'environment'),) + __table_args__ = (UniqueConstraint("squad", "environment"),) class Gcloud_provider(Base): @@ -58,7 +60,7 @@ class Gcloud_provider(Base): squad = Column(String(200), nullable=False) gcloud_keyfile_json = Column(String(5000), nullable=False) created_at = Column(DateTime, default=datetime.datetime.now()) - __table_args__ = (UniqueConstraint('squad', 'environment'),) + __table_args__ = (UniqueConstraint("squad", "environment"),) class Azure_provider(Base): @@ -71,7 +73,7 @@ class Azure_provider(Base): subscription_id = Column(String(200), nullable=False) tenant_id = Column(String(200), nullable=False) created_at = Column(DateTime, default=datetime.datetime.now()) - __table_args__ = (UniqueConstraint('squad', 'environment'),) + __table_args__ = (UniqueConstraint("squad", "environment"),) class Deploy(Base): @@ -93,8 +95,7 @@ class Deploy(Base): environment = Column(String(50)) tfvar_file = Column(String(50)) project_path = Column(String(50)) - __table_args__ = (UniqueConstraint( - 'squad', 'environment', 'name', 'stack_name'),) + __table_args__ = (UniqueConstraint("squad", "environment", "name", "stack_name"),) class Tasks(Base): diff --git a/sld-api-backend/helpers/get_data.py b/sld-api-backend/helpers/get_data.py index ccb604ba..5b003538 100644 --- a/sld-api-backend/helpers/get_data.py +++ b/sld-api-backend/helpers/get_data.py @@ -1,18 +1,22 @@ -from fastapi import HTTPException -from celery.result import AsyncResult -from datetime import datetime from functools import wraps -from croniter import croniter -import redis -from crud import stacks as crud_stacks +import redis +from celery.result import AsyncResult +from config.api import settings +from croniter import croniter +from crud import activityLogs as crud_activity from crud import deploys as crud_deploys +from crud import stacks as crud_stacks from crud import user as crud_users -from crud import activityLogs as crud_activity -from config.api import settings +from fastapi import HTTPException -r = redis.Redis(host=settings.BACKEND_SERVER, port=6379, db=2, - charset="utf-8", decode_responses=True) +r = redis.Redis( + host=settings.BACKEND_SERVER, + port=6379, + db=2, + charset="utf-8", + decode_responses=True, +) def check_squad_user(squad_owner: list, squad_add: list) -> bool: @@ -20,15 +24,34 @@ def check_squad_user(squad_owner: list, squad_add: list) -> bool: def check_role_user(role_owner: list, role_add: list) -> bool: - less_roles = ['stormtrooper', 'R2-D2', 'grogu'] + less_roles = ["stormtrooper", "R2-D2", "grogu"] role = role_owner + less_roles return all(item in role for item in role_add) +def check_squad_stack( + db, current_user: str, current_user_squad: list, stack_squad_access: list +) -> bool: + # Check if the user with squad * not have role yoda + if not crud_users.is_master(db, current_user): + if "darth_vader" not in current_user.role: + raise HTTPException( + status_code=403, detail=f"Not enough permissions for create a stack" + ) + if "*" in stack_squad_access and "yoda" not in current_user.role: + raise HTTPException( + status_code=403, + detail="It is not possible to use * squad when role is not yoda", + ) + if not all(__squad in current_user_squad for __squad in stack_squad_access): + raise HTTPException( + status_code=403, + detail=f"Not enough permissions for some of these squads {stack_squad_access}", + ) + + def user_squad_scope(db, user, squad): try: - print(user) - print(squad) if user.isdigit(): user_info = crud_users.get_user_by_id(db=db, id=user) else: @@ -37,77 +60,65 @@ def user_squad_scope(db, user, squad): raise ValueError(f"User {user} no exists") return bool(set(user_info.squad).intersection(squad)) except Exception as err: - raise HTTPException( - status_code=400, - detail=str(err)) + raise HTTPException(status_code=400, detail=str(err)) def stack(db, stack_name: str): try: - stack_data = crud_stacks.get_stack_by_name( - db=db, stack_name=stack_name) + stack_data = crud_stacks.get_stack_by_name(db=db, stack_name=stack_name) if stack_data is None: raise Exception("Stack Name Not Found") return stack_data except Exception as err: - raise HTTPException( - status_code=404, - detail=f"{err}") + raise HTTPException(status_code=404, detail=f"{err}") def deploy(db, deploy_id: int): try: - deploy_data = crud_deploys.get_deploy_by_id( - db=db, deploy_id=deploy_id) + deploy_data = crud_deploys.get_deploy_by_id(db=db, deploy_id=deploy_id) if deploy_data is None: raise Exception("Deploy id Not Found") return deploy_data except Exception as err: - raise HTTPException( - status_code=404, - detail=f"{err}") + raise HTTPException(status_code=404, detail=f"{err}") def deploy_squad(db, deploy_id: int, squad: str): try: deploy_data = crud_deploys.get_deploy_by_id_squad( - db=db, deploy_id=deploy_id, squad=squad) + db=db, deploy_id=deploy_id, squad=squad + ) if deploy_data is None: raise Exception("Deploy id Not Found") return deploy_data except Exception as err: - raise HTTPException( - status_code=404, - detail=f"{err}") + raise HTTPException(status_code=404, detail=f"{err}") def get_deploy(db, deploy_id: int): try: - deploy_data = crud_deploys.get_deploy_by_id( - db=db, deploy_id=deploy_id) + deploy_data = crud_deploys.get_deploy_by_id(db=db, deploy_id=deploy_id) if deploy_data is None: raise Exception("Deploy id Not Found") return deploy_data except Exception as err: - raise HTTPException( - status_code=404, - detail=f"{err}") + raise HTTPException(status_code=404, detail=f"{err}") def check_deploy_exist(db, deploy_name: str, squad: str, env: str, stack: str): - data_source_check = f'{deploy_name}-{squad}-{env}-{stack}' + data_source_check = f"{deploy_name}-{squad}-{env}-{stack}" try: db_data = crud_deploys.get_deploy_by_name_squad( - db=db, deploy_name=deploy_name, squad=squad, environment=env) + db=db, deploy_name=deploy_name, squad=squad, environment=env + ) if db_data is not None: - data_db_check = f'{db_data.name}-{db_data.squad}-{db_data.environment}-{db_data.stack_name}' + data_db_check = f"{db_data.name}-{db_data.squad}-{db_data.environment}-{db_data.stack_name}" if data_source_check == data_db_check: raise Exception( - "The name of the deployment already exists in the current squad and with specified environment") + "The name of the deployment already exists in the current squad and with specified environment" + ) except Exception as err: - raise HTTPException( - status_code=409, - detail=f"{err}") + raise HTTPException(status_code=409, detail=f"{err}") def check_deploy_state(task_id: str): @@ -124,10 +135,11 @@ def check_deploy_task_pending_state(deploy_name, squad, environment, task_id=Non return True try: if r.exists(f"{deploy_name}-{squad}-{environment}"): - raise Exception("Task already exists in pending state waiting to be executed") + raise Exception( + "Task already exists in pending state waiting to be executed" + ) except Exception as err: - raise HTTPException( - status_code=409, detail=f"{err}") + raise HTTPException(status_code=409, detail=f"{err}") r.set(f"{deploy_name}-{squad}-{environment}", "Locked") r.expire(f"{deploy_name}-{squad}-{environment}", settings.TASK_LOCKED_EXPIRED) @@ -139,17 +151,18 @@ def check_providers(stack_name): else: raise HTTPException( status_code=404, - detail=f"stack name {stack_name.lower()} no content providers support name preffix: {providers_support}") + detail=f"stack name {stack_name.lower()} no content providers support name preffix: {providers_support}", + ) def activity_log(func): @wraps(func) async def wrapper(*args, **kwargs): crud_activity.create_activity_log( - db=kwargs['db'], - username=kwargs['current_user'].username, - squad=kwargs['current_user'].squad, - action=f'Delete User {kwargs["user"]}' + db=kwargs["db"], + username=kwargs["current_user"].username, + squad=kwargs["current_user"].squad, + action=f'Delete User {kwargs["user"]}', ) return await func(*args, **kwargs) diff --git a/sld-api-backend/helpers/push_task.py b/sld-api-backend/helpers/push_task.py index 94fd6faa..8606dc2f 100644 --- a/sld-api-backend/helpers/push_task.py +++ b/sld-api-backend/helpers/push_task.py @@ -1,143 +1,149 @@ import json -from fastapi import HTTPException - -from tasks.celery_worker import (git, unlock, output, show) -from tasks.celery_worker import (get_variable_list, get_variable_json) -from tasks.celery_worker import (schedules_list, schedule_get, schedule_add, schedule_delete, schedule_update) -from tasks.celery_worker import (pipeline_plan, pipeline_deploy, pipeline_destroy, pipeline_git_pull) from config.api import settings +from fastapi import HTTPException +from tasks.celery_worker import (get_variable_json, get_variable_list, output, + pipeline_deploy, pipeline_destroy, + pipeline_git_pull, pipeline_plan, + schedule_add, schedule_delete, schedule_get, + schedule_update, schedules_list, show, unlock) def async_deploy( - git_repo: str, - name: str, - stack_name: str, - environment: str, - squad: str, - branch: str, - tf_ver: str, - variables: dict, - secreto: str, - variables_file: str = "", - project_path: str = "" - ): + git_repo: str, + name: str, + stack_name: str, + environment: str, + squad: str, + branch: str, + tf_ver: str, + variables: dict, + secreto: str, + variables_file: str = "", + project_path: str = "", +): queue = "any" if not settings.TASK_ROUTE else squad pipeline_deploy_result = pipeline_deploy.s( - git_repo=git_repo, - name=name, - stack_name=stack_name, - environment=environment, - squad=squad, - branch=branch, - version=tf_ver, - kwargs=variables, - secreto=secreto, - variables_file=variables_file, - project_path=project_path - ).apply_async(queue=queue, - retry=True, - retry_policy={ - 'max_retries': settings.TASK_MAX_RETRY, - 'interval_start': settings.TASK_RETRY_INTERVAL, - } - ) + git_repo=git_repo, + name=name, + stack_name=stack_name, + environment=environment, + squad=squad, + branch=branch, + version=tf_ver, + kwargs=variables, + secreto=secreto, + variables_file=variables_file, + project_path=project_path, + ).apply_async( + queue=queue, + retry=True, + retry_policy={ + "max_retries": settings.TASK_MAX_RETRY, + "interval_start": settings.TASK_RETRY_INTERVAL, + }, + ) return pipeline_deploy_result.task_id def async_destroy( - git_repo: str, - name: str, - stack_name: str, - environment: str, - squad: str, - branch: str, - tf_ver: str, - variables: dict, - secreto: str, - variables_file: str = "", - project_path: str = "" - ): + git_repo: str, + name: str, + stack_name: str, + environment: str, + squad: str, + branch: str, + tf_ver: str, + variables: dict, + secreto: str, + variables_file: str = "", + project_path: str = "", +): queue = "any" if not settings.TASK_ROUTE else squad pipeline_destroy_result = pipeline_destroy.s( - git_repo=git_repo, - name=name, - stack_name=stack_name, - environment=environment, - squad=squad, - branch=branch, - version=tf_ver, - kwargs=variables, - secreto=secreto, - variables_file=variables_file, - project_path=project_path - ).apply_async( - queue=queue, - retry=True, - retry_policy={ - 'max_retries': settings.TASK_MAX_RETRY, - 'interval_start': settings.TASK_RETRY_INTERVAL, - } - ) + git_repo=git_repo, + name=name, + stack_name=stack_name, + environment=environment, + squad=squad, + branch=branch, + version=tf_ver, + kwargs=variables, + secreto=secreto, + variables_file=variables_file, + project_path=project_path, + ).apply_async( + queue=queue, + retry=True, + retry_policy={ + "max_retries": settings.TASK_MAX_RETRY, + "interval_start": settings.TASK_RETRY_INTERVAL, + }, + ) return pipeline_destroy_result.task_id def async_plan( - git_repo: str, - name: str, - stack_name: str, - environment: str, - squad: str, - branch: str, - tf_ver: str, - variables: dict, - secreto: str, - variables_file: str = "", - project_path: str = "" - ): + git_repo: str, + name: str, + stack_name: str, + environment: str, + squad: str, + branch: str, + tf_ver: str, + variables: dict, + secreto: str, + variables_file: str = "", + project_path: str = "", +): queue = "any" if not settings.TASK_ROUTE else squad pipeline_plan_result = pipeline_plan.s( - git_repo=git_repo, - name=name, - stack_name=stack_name, - environment=environment, - squad=squad, - branch=branch, - version=tf_ver, - kwargs=variables, - secreto=secreto, - variables_file=variables_file, - project_path=project_path - ).apply_async(queue=queue, - retry=True, - retry_policy={ - 'max_retries': settings.TASK_MAX_RETRY, - 'interval_start': settings.TASK_RETRY_INTERVAL, - } - ) + git_repo=git_repo, + name=name, + stack_name=stack_name, + environment=environment, + squad=squad, + branch=branch, + version=tf_ver, + kwargs=variables, + secreto=secreto, + variables_file=variables_file, + project_path=project_path, + ).apply_async( + queue=queue, + retry=True, + retry_policy={ + "max_retries": settings.TASK_MAX_RETRY, + "interval_start": settings.TASK_RETRY_INTERVAL, + }, + ) return pipeline_plan_result.task_id def async_output(stack_name: str, environment: str, squad: str, name: str): - output_result = output.s(stack_name, environment, squad, - name).apply_async(queue="squad") + output_result = output.s(stack_name, environment, squad, name).apply_async( + queue="squad" + ) return output_result.task_id def async_unlock(stack_name: str, environment: str, squad: str, name: str): - unlock_result = unlock.s(stack_name, environment, squad, - name).apply_async(queue="squad") + unlock_result = unlock.s(stack_name, environment, squad, name).apply_async( + queue="squad" + ) return unlock_result.task_id def async_schedule_delete(deploy_name: str, squad: str): - deploy_schedule_delete_result = schedule_delete.s(deploy_name).apply_async(queue="squad") + deploy_schedule_delete_result = schedule_delete.s(deploy_name).apply_async( + queue="squad" + ) return deploy_schedule_delete_result.task_id @@ -162,57 +168,53 @@ def async_schedule_update(deploy_name: str): def async_show(stack_name: str, environment: str, squad: str, name: str): - show_result = show.s(stack_name, environment, squad, - name).apply_async(queue="squad") + show_result = show.s(stack_name, environment, squad, name).apply_async( + queue="squad" + ) return show_result.task_id def sync_git( - stack_name: str, - git_repo: str, - branch: str, - environment: str, - squad: str, - name: str): + stack_name: str, git_repo: str, branch: str, environment: str, squad: str, name: str +): try: pipeline_git_result = pipeline_git_pull.s( - stack_name=stack_name, - git_repo=git_repo, - branch=branch, - environment=environment, - squad=squad, - name=name).apply_async(queue="squad") + stack_name=stack_name, + git_repo=git_repo, + branch=branch, + environment=environment, + squad=squad, + name=name, + ).apply_async(queue="squad") task_id = pipeline_git_result.task_id get_data = pipeline_git_result.get() try: - data = json.loads(get_data.get('stdout')) - except Exception as err: - raise ValueError(get_data.get('result')) + data = json.loads(get_data.get("stdout")) + except Exception: + raise ValueError(get_data.get("result")) return task_id, data except Exception as err: - raise HTTPException(status_code=408, - detail=f"{err}") + raise HTTPException(status_code=408, detail=f"{err}") def sync_get_vars( - stack_name: str, - environment: str, - squad: str, - name: str, - task_id, - otype: str): + stack_name: str, environment: str, squad: str, name: str, task_id, otype: str +): try: if otype == "json": data_json = get_variable_json.apply_async( - queue=squad, args=(stack_name, environment, squad, name)) + queue=squad, args=(stack_name, environment, squad, name) + ) variables_json = json.loads(data_json.get()) return variables_json elif otype == "list": data_list = get_variable_list.apply_async( - queue=squad, args=(stack_name, environment, squad, name)) + queue=squad, args=(stack_name, environment, squad, name) + ) variables_list = data_list.get() return variables_list except Exception as err: raise HTTPException( - status_code=404, - detail=f"Variable File Not Found check task {task_id} {err}") + status_code=404, + detail=f"Variable File Not Found check task {task_id} {err}", + ) diff --git a/sld-api-backend/helpers/schedule.py b/sld-api-backend/helpers/schedule.py index 5f7a9265..5c95a00c 100644 --- a/sld-api-backend/helpers/schedule.py +++ b/sld-api-backend/helpers/schedule.py @@ -1,11 +1,13 @@ import datetime -#from dateutil import parser + +# from dateutil import parser import requests -from fastapi import HTTPException from config.api import settings +from fastapi import HTTPException server = settings.SCHEDULE_SERVER + def resource_life_cycle(start_time: str, end_time: str) -> bool: if start_time == 0: return None @@ -25,27 +27,19 @@ def resource_life_cycle(start_time: str, end_time: str) -> bool: return start <= now_param or now_param <= end - - -def request_url(verb: str, headers: dict = '', uri: str = '', json: dict = ''): - response = requests.request( - verb, - headers=headers, - url=f'{server}/{uri}', - json=json - ) +def request_url(verb: str, headers: dict = "", uri: str = "", json: dict = ""): + response = requests.request(verb, headers=headers, url=f"{server}/{uri}", json=json) try: - result = {'status_code': response.status_code, - 'content': response.content.decode('utf-8'), - 'json': response.json() - } + result = { + "status_code": response.status_code, + "content": response.content.decode("utf-8"), + "json": response.json(), + } return result except Exception as err: - raise HTTPException( - status_code=501, - detail=f"{err}") + raise HTTPException(status_code=501, detail=f"{err}") def check_status(): - response = request_url(verb='GET') + response = request_url(verb="GET") return response diff --git a/sld-api-backend/main.py b/sld-api-backend/main.py index 9daf567b..ed7183ca 100644 --- a/sld-api-backend/main.py +++ b/sld-api-backend/main.py @@ -1,19 +1,21 @@ -from fastapi import FastAPI +import logging from api_v1.api import api_router from config.api import settings from config.database import engine from db import models -import logging +from fastapi import FastAPI log = logging.getLogger(__name__) log.setLevel(logging.DEBUG) models.Base.metadata.create_all(bind=engine) -app = FastAPI(title=f"{settings.PROJECT_NAME}", - description=f"{settings.DESCRIPTION}", - openapi_url=f"{settings.API_V1_STR}/openapi.json", - version=f"{settings.VERSION}",) +app = FastAPI( + title=f"{settings.PROJECT_NAME}", + description=f"{settings.DESCRIPTION}", + openapi_url=f"{settings.API_V1_STR}/openapi.json", + version=f"{settings.VERSION}", +) app.include_router(api_router, prefix=settings.API_V1_STR) diff --git a/sld-api-backend/schemas/schemas.py b/sld-api-backend/schemas/schemas.py index 1656674c..076b20a5 100644 --- a/sld-api-backend/schemas/schemas.py +++ b/sld-api-backend/schemas/schemas.py @@ -1,5 +1,6 @@ -from pydantic import BaseModel, EmailStr, Field, ValidationError, validator, SecretStr, constr -from typing import Optional, List +from typing import List, Optional + +from pydantic import BaseModel, EmailStr, Field, constr class UserBase(BaseModel): @@ -66,7 +67,7 @@ class TokenData(BaseModel): class StackBase(BaseModel): stack_name: constr(strip_whitespace=True) git_repo: constr(strip_whitespace=True) - branch: constr(strip_whitespace=True) = "master" + branch: constr(strip_whitespace=True) = "master" squad_access: List[str] = ["*"] tf_version: constr(strip_whitespace=True) = "1.2.3" description: constr(strip_whitespace=True) @@ -89,7 +90,9 @@ class AwsBase(BaseModel): squad: constr(strip_whitespace=True) environment: constr(strip_whitespace=True) access_key_id: constr(strip_whitespace=True) - secret_access_key: Optional[constr(strip_whitespace=True)] = Field(None, example="string") + secret_access_key: Optional[constr(strip_whitespace=True)] = Field( + None, example="string" + ) default_region: constr(strip_whitespace=True) @@ -151,9 +154,15 @@ class DeployCreate(BaseModel): stack_name: constr(strip_whitespace=True) stack_branch: Optional[constr(strip_whitespace=True)] = Field("", example="") environment: constr(strip_whitespace=True) - start_time: Optional[constr(strip_whitespace=True)] = Field(None, example="30 7 * * 0-4") - destroy_time: Optional[constr(strip_whitespace=True)] = Field(None, example="30 18 * * 0-4") - tfvar_file: Optional[constr(strip_whitespace=True)] = Field("", example="terraform.tfvars") + start_time: Optional[constr(strip_whitespace=True)] = Field( + None, example="30 7 * * 0-4" + ) + destroy_time: Optional[constr(strip_whitespace=True)] = Field( + None, example="30 18 * * 0-4" + ) + tfvar_file: Optional[constr(strip_whitespace=True)] = Field( + "", example="terraform.tfvars" + ) project_path: Optional[constr(strip_whitespace=True)] = Field("", example="") variables: dict @@ -170,7 +179,9 @@ class DeployUpdate(BaseModel): start_time: constr(strip_whitespace=True) destroy_time: constr(strip_whitespace=True) stack_branch: Optional[constr(strip_whitespace=True)] = Field("", example="") - tfvar_file: Optional[constr(strip_whitespace=True)] = Field("", example="terraform.tfvars") + tfvar_file: Optional[constr(strip_whitespace=True)] = Field( + "", example="terraform.tfvars" + ) project_path: Optional[constr(strip_whitespace=True)] = Field("", example="") variables: dict @@ -190,9 +201,15 @@ class PlanCreate(BaseModel): stack_branch: Optional[constr(strip_whitespace=True)] = Field("", example="") squad: constr(strip_whitespace=True) environment: constr(strip_whitespace=True) - start_time: Optional[constr(strip_whitespace=True)] = Field(None, example="30 7 * * 0-4") - destroy_time: Optional[constr(strip_whitespace=True)] = Field(None, example="30 18 * * 0-4") - tfvar_file: Optional[constr(strip_whitespace=True)] = Field("", example="terraform.tfvars") + start_time: Optional[constr(strip_whitespace=True)] = Field( + None, example="30 7 * * 0-4" + ) + destroy_time: Optional[constr(strip_whitespace=True)] = Field( + None, example="30 18 * * 0-4" + ) + tfvar_file: Optional[constr(strip_whitespace=True)] = Field( + "", example="terraform.tfvars" + ) project_path: Optional[constr(strip_whitespace=True)] = Field("", example="s") variables: dict @@ -214,5 +231,9 @@ class Config: class ScheduleUpdate(BaseModel): - start_time: Optional[constr(strip_whitespace=True)] = Field(None, example="30 7 * * 0-4") - destroy_time: Optional[constr(strip_whitespace=True)] = Field(None, example="30 18 * * 0-4") + start_time: Optional[constr(strip_whitespace=True)] = Field( + None, example="30 7 * * 0-4" + ) + destroy_time: Optional[constr(strip_whitespace=True)] = Field( + None, example="30 18 * * 0-4" + ) diff --git a/sld-api-backend/security/deps.py b/sld-api-backend/security/deps.py index 9a7b5911..de88066f 100644 --- a/sld-api-backend/security/deps.py +++ b/sld-api-backend/security/deps.py @@ -1,17 +1,16 @@ from typing import Generator +from config.api import settings +from config.database import SessionLocal +from crud import user as crud_users +from db import models from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer from jose import jwt from pydantic import ValidationError -from sqlalchemy.orm import Session - -from crud import user as crud_users -from db import models from schemas import schemas from security import tokens -from config.api import settings -from config.database import SessionLocal +from sqlalchemy.orm import Session reusable_oauth2 = OAuth2PasswordBearer( tokenUrl=f"{settings.API_V1_STR}/authenticate/access-token" @@ -27,8 +26,8 @@ def get_db() -> Generator: def get_current_user( - token: str = Depends(reusable_oauth2), - db: Session = Depends(get_db)): + token: str = Depends(reusable_oauth2), db: Session = Depends(get_db) +): credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", @@ -68,23 +67,32 @@ def get_current_active_superuser( def validate_password(password: str): - SpecialSymbol = ['$', '@', '#', '%', '.', '!', '&', '"', '?'] + SpecialSymbol = ["$", "@", "#", "%", ".", "!", "&", '"', "?"] if len(password) < settings.PASSWORD_LEN: raise HTTPException( - status_code=400, detail=f"Make sure your password is at lest {settings.PASSWORD_LEN} letters") + status_code=400, + detail=f"Make sure your password is at lest {settings.PASSWORD_LEN} letters", + ) if len(password) > 20: raise HTTPException( - status_code=400, detail="length should be not be greater than 20") + status_code=400, detail="length should be not be greater than 20" + ) if not any(char.isdigit() for char in password): raise HTTPException( - status_code=400, detail="Make sure your password has a number in it") + status_code=400, detail="Make sure your password has a number in it" + ) if not any(char.isupper() for char in password): raise HTTPException( - status_code=400, detail="Make sure your password has a capital letter in it") + status_code=400, detail="Make sure your password has a capital letter in it" + ) if not any(char.islower() for char in password): raise HTTPException( - status_code=400, detail="Make sure your password has a lowercase letter in it") + status_code=400, + detail="Make sure your password has a lowercase letter in it", + ) if not any(char in SpecialSymbol for char in password): raise HTTPException( - status_code=400, detail="Make sure your password has a one of the symbols $@#% in it") + status_code=400, + detail="Make sure your password has a one of the symbols $@#% in it", + ) return True diff --git a/sld-api-backend/security/providers_credentials.py b/sld-api-backend/security/providers_credentials.py index 549ebf5e..acb32639 100644 --- a/sld-api-backend/security/providers_credentials.py +++ b/sld-api-backend/security/providers_credentials.py @@ -1,8 +1,8 @@ -import os import ast +import configparser import json import logging -import configparser +import os from config.api import settings @@ -20,24 +20,32 @@ def aws_config(secreto): try: config = configparser.ConfigParser(strict=False) # Check if pass me profile - if secreto.get('data')['profile_name']: + if secreto.get("data")["profile_name"]: # Create folder in home user createLocalFolder(settings.AWS_CONGIG_DEFAULT_FOLDER) # Read config config.read(settings.AWS_SHARED_CONFIG_FILE) - profile_name = secreto.get('data')['profile_name'] - if not config.has_section(f'profile {profile_name}'): - config.add_section(f'profile {profile_name}') - config.set(f'profile {profile_name}', 'role_arn', secreto.get( - 'data')['role_arn']) - config.set(f'profile {profile_name}', 'region', secreto.get( - 'data')['default_region']) - config.set(f'profile {profile_name}', 'source_profile', secreto.get( - 'data')['source_profile']) - with open(settings.AWS_SHARED_CONFIG_FILE, 'w') as configfile: + profile_name = secreto.get("data")["profile_name"] + if not config.has_section(f"profile {profile_name}"): + config.add_section(f"profile {profile_name}") + config.set( + f"profile {profile_name}", "role_arn", secreto.get("data")["role_arn"] + ) + config.set( + f"profile {profile_name}", + "region", + secreto.get("data")["default_region"], + ) + config.set( + f"profile {profile_name}", + "source_profile", + secreto.get("data")["source_profile"], + ) + with open(settings.AWS_SHARED_CONFIG_FILE, "w") as configfile: config.write(configfile) logging.info( - f"create config {profile_name} in {settings.AWS_SHARED_CONFIG_FILE} done") + f"create config {profile_name} in {settings.AWS_SHARED_CONFIG_FILE} done" + ) del secreto del profile_name del configfile @@ -51,21 +59,25 @@ def aws_config(secreto): def aws_credentials(secreto): try: config = configparser.ConfigParser(strict=False) - if secreto.get('data')['source_profile']: + if secreto.get("data")["source_profile"]: config.read(settings.AWS_SHARED_CREDENTIALS_FILE) - source_profile = secreto.get('data')['source_profile'] + source_profile = secreto.get("data")["source_profile"] if not config.has_section(source_profile): config.add_section(source_profile) - config.set(source_profile, 'region', - secreto.get('data')['default_region']) - config.set(source_profile, 'aws_access_key_id', - secreto.get("data")["access_key"]) - config.set(source_profile, 'aws_secret_access_key', - secreto.get("data")["secret_access_key"]) - with open(settings.AWS_SHARED_CREDENTIALS_FILE, 'w') as credentialsfile: + config.set(source_profile, "region", secreto.get("data")["default_region"]) + config.set( + source_profile, "aws_access_key_id", secreto.get("data")["access_key"] + ) + config.set( + source_profile, + "aws_secret_access_key", + secreto.get("data")["secret_access_key"], + ) + with open(settings.AWS_SHARED_CREDENTIALS_FILE, "w") as credentialsfile: config.write(credentialsfile) logging.info( - f"create credentials {source_profile} in {settings.AWS_SHARED_CREDENTIALS_FILE} done") + f"create credentials {source_profile} in {settings.AWS_SHARED_CREDENTIALS_FILE} done" + ) del secreto del source_profile del credentialsfile @@ -77,67 +89,67 @@ def aws_credentials(secreto): def secret( - stack_name, - environment, - squad, name, - secreto, + stack_name, + environment, + squad, + name, + secreto, ): if any(i in stack_name.lower() for i in settings.AWS_PREFIX): try: if not aws_config(secreto) or not aws_credentials(secreto): - os.environ["AWS_ACCESS_KEY_ID"] = secreto.get("data")[ - "access_key"] + os.environ["AWS_ACCESS_KEY_ID"] = secreto.get("data")["access_key"] os.environ["AWS_SECRET_ACCESS_KEY"] = secreto.get("data")[ - "secret_access_key"] - logging.info(f"Set aws account without asume role {squad}, {environment}, {stack_name}, {name}") + "secret_access_key" + ] + logging.info( + f"Set aws account without asume role {squad}, {environment}, {stack_name}, {name}" + ) except Exception as err: logging.warning(err) elif any(i in stack_name.lower() for i in settings.GCLOUD_PREFIX): gcloud_keyfile = f"/tmp/{stack_name}/{environment}/{squad}/{name}/gcp_{environment}_{stack_name}_{name}.json" gcloud_keyfile_data = ast.literal_eval( - secreto.get("data")["gcloud_keyfile_json"]) - with open(gcloud_keyfile, 'w') as gcloud_file: + secreto.get("data")["gcloud_keyfile_json"] + ) + with open(gcloud_keyfile, "w") as gcloud_file: json.dump(gcloud_keyfile_data, gcloud_file, indent=4) os.environ["GOOGLE_CLOUD_KEYFILE_JSON"] = gcloud_keyfile elif any(i in stack_name.lower() for i in settings.AZURE_PREFIX): os.environ["ARM_CLIENT_ID"] = secreto.get("data")["client_id"] - os.environ["ARM_CLIENT_SECRET"] = secreto.get("data")[ - "client_secret"] - os.environ["ARM_SUBSCRIPTION_ID"] = secreto.get("data")[ - "subscription_id"] + os.environ["ARM_CLIENT_SECRET"] = secreto.get("data")["client_secret"] + os.environ["ARM_SUBSCRIPTION_ID"] = secreto.get("data")["subscription_id"] os.environ["ARM_TENANT_ID"] = secreto.get("data")["tenant_id"] def unsecret(stack_name, environment, squad, name, secreto): if any(i in stack_name.lower() for i in settings.AWS_PREFIX): try: - if secreto.get('data')['profile_name']: + if secreto.get("data")["profile_name"]: config = configparser.ConfigParser(strict=False) config.read(settings.AWS_SHARED_CONFIG_FILE) - profile_name = secreto.get('data')['profile_name'] - config.remove_option(f'profile {profile_name}', 'role_arn') - config.remove_option(f'profile {profile_name}', 'region') - config.remove_option( - f'profile {profile_name}', 'source_profile') - config.remove_section(f'profile {profile_name}') - with open(settings.AWS_SHARED_CONFIG_FILE, 'w') as configfile: + profile_name = secreto.get("data")["profile_name"] + config.remove_option(f"profile {profile_name}", "role_arn") + config.remove_option(f"profile {profile_name}", "region") + config.remove_option(f"profile {profile_name}", "source_profile") + config.remove_section(f"profile {profile_name}") + with open(settings.AWS_SHARED_CONFIG_FILE, "w") as configfile: config.write(configfile) logging.info(f"remove config {profile_name} done") del config - if secreto.get('data')['source_profile']: + if secreto.get("data")["source_profile"]: config = configparser.ConfigParser(strict=False) config.read(settings.AWS_SHARED_CREDENTIALS_FILE) - source_profile = secreto.get('data')['source_profile'] - config.remove_option(source_profile, 'region') - config.remove_option(source_profile, 'aws_access_key_id') - config.remove_option( - source_profile, 'aws_secret_access_key') + source_profile = secreto.get("data")["source_profile"] + config.remove_option(source_profile, "region") + config.remove_option(source_profile, "aws_access_key_id") + config.remove_option(source_profile, "aws_secret_access_key") config.remove_section(source_profile) - with open(settings.AWS_SHARED_CREDENTIALS_FILE, 'w') as credentialsfile: + with open(settings.AWS_SHARED_CREDENTIALS_FILE, "w") as credentialsfile: config.write(credentialsfile) logging.info(f"remove credentials {source_profile} done") del config @@ -153,5 +165,3 @@ def unsecret(stack_name, environment, squad, name, secreto): os.environ.pop("ARM_CLIENT_SECRET") os.environ.pop("ARM_SUBSCRIPTION_ID") os.environ.pop("ARM_TENANT_ID") - - diff --git a/sld-api-backend/security/tokens.py b/sld-api-backend/security/tokens.py index 751301ac..d356e01f 100644 --- a/sld-api-backend/security/tokens.py +++ b/sld-api-backend/security/tokens.py @@ -1,15 +1,14 @@ from datetime import datetime, timedelta from typing import Any, Union -from jose import jwt -from passlib.context import CryptContext -from fastapi import HTTPException - from config.api import settings -from crud import user as crud_users from crud import aws as crud_aws -from crud import gcp as crud_gcp from crud import azure as crud_azure +from crud import gcp as crud_gcp +from crud import user as crud_users +from fastapi import HTTPException +from jose import jwt +from passlib.context import CryptContext pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") @@ -25,7 +24,8 @@ def create_access_token( ) to_encode = {"exp": expire, "sub": str(subject)} encoded_jwt = jwt.encode( - to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM) + to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM + ) return encoded_jwt @@ -39,10 +39,7 @@ def get_password_hash(password: str) -> str: def decode_access_token(*, data: str): token = data - return jwt.decode( - token, - settings.SECRET_KEY, - algorithms=settings.ALGORITHM) + return jwt.decode(token, settings.SECRET_KEY, algorithms=settings.ALGORITHM) def validate_user(db, user: str, plain_passwd: str): @@ -52,15 +49,12 @@ def validate_user(db, user: str, plain_passwd: str): except Exception: pass if not user: - raise HTTPException( - status_code=404, detail="Incorrect username or password") + raise HTTPException(status_code=404, detail="Incorrect username or password") elif not verify_password(plain_passwd, hash_passwd): - raise HTTPException( - status_code=403, detail="Incorrect username or password") + raise HTTPException(status_code=403, detail="Incorrect username or password") elif not crud_users.is_active(db, user): raise HTTPException(status_code=403, detail="Inactive user") - access_token_expires = timedelta( - minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) + access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) return { "access_token": create_access_token( user.id, expires_delta=access_token_expires @@ -73,21 +67,26 @@ def check_prefix(db, stack_name: str, environment: str, squad: str): try: if any(i in stack_name.lower() for i in settings.AWS_PREFIX): secreto = crud_aws.get_credentials_aws_profile( - db=db, environment=environment, squad=squad) + db=db, environment=environment, squad=squad + ) return secreto elif any(i in stack_name.lower() for i in settings.GCLOUD_PREFIX): secreto = crud_gcp.get_credentials_gcloud_profile( - db=db, environment=environment, squad=squad) + db=db, environment=environment, squad=squad + ) return secreto elif any(i in stack_name.lower() for i in settings.AZURE_PREFIX): secreto = crud_azure.get_credentials_azure_profile( - db=db, environment=environment, squad=squad) + db=db, environment=environment, squad=squad + ) return secreto else: raise HTTPException( status_code=404, - detail=f"stack name {stack_name.lower()} no content providers support name preffix: {settings.PROVIDERS_SUPPORT} ") + detail=f"stack name {stack_name.lower()} no content providers support name preffix: {settings.PROVIDERS_SUPPORT} ", + ) except Exception as err: raise HTTPException( status_code=400, - detail=f"stack name {stack_name.lower()} env {environment} error {err} ") + detail=f"stack name {stack_name.lower()} env {environment} error {err} ", + ) diff --git a/sld-api-backend/security/vault.py b/sld-api-backend/security/vault.py index ce629fba..9413d04d 100644 --- a/sld-api-backend/security/vault.py +++ b/sld-api-backend/security/vault.py @@ -1,6 +1,5 @@ -from cryptography.fernet import Fernet - from config.api import settings +from cryptography.fernet import Fernet def vault_encrypt(func): @@ -8,8 +7,9 @@ def wrap(*args, **kwargs): key = settings.SECRET_VAULT f = Fernet(key) data = func(*args, **kwargs) - token = f.encrypt(bytes(data, 'utf-8')) - return token.decode('utf-8') + token = f.encrypt(bytes(data, "utf-8")) + return token.decode("utf-8") + return wrap @@ -18,6 +18,7 @@ def wrap(*args, **kwargs): key = settings.SECRET_VAULT f = Fernet(key) data = func(*args, **kwargs) - token = f.decrypt(bytes(data, 'utf-8')) - return token.decode('utf-8') + token = f.decrypt(bytes(data, "utf-8")) + return token.decode("utf-8") + return wrap diff --git a/sld-api-backend/tasks/celery_worker.py b/sld-api-backend/tasks/celery_worker.py index 24cb4fc1..243a16de 100644 --- a/sld-api-backend/tasks/celery_worker.py +++ b/sld-api-backend/tasks/celery_worker.py @@ -1,91 +1,129 @@ import logging +import traceback + import redis -from config.celery_config import celery_app from celery import states -from celery.exceptions import Ignore, TimeLimitExceeded -import traceback +from celery.exceptions import Ignore +from config.api import settings +from config.celery_config import celery_app from core.providers.terraform import TerraformActions as tf from helpers.schedule import request_url -from config.api import settings - -r = redis.Redis(host=settings.BACKEND_SERVER, port=6379, db=2, - charset="utf-8", decode_responses=True) +r = redis.Redis( + host=settings.BACKEND_SERVER, + port=6379, + db=2, + charset="utf-8", + decode_responses=True, +) -@celery_app.task(bind=True, acks_late=True, time_limit=settings.DEPLOY_TMOUT, name='pipeline Deploy') +@celery_app.task( + bind=True, acks_late=True, time_limit=settings.DEPLOY_TMOUT, name="pipeline Deploy" +) def pipeline_deploy( - self, - git_repo: str, - name: str, - stack_name: str, - environment: str, - squad: str, - branch: str, - version: str, - kwargs: any, - secreto: str, - variables_file: str = "", - project_path: str = "" - ): - filter_kwargs = {key: value for ( - key, value) in kwargs.items() if "pass" not in key} + self, + git_repo: str, + name: str, + stack_name: str, + environment: str, + squad: str, + branch: str, + version: str, + kwargs: any, + secreto: str, + variables_file: str = "", + project_path: str = "", +): + filter_kwargs = {key: value for (key, value) in kwargs.items() if "pass" not in key} try: r.set(f"{name}-{squad}-{environment}", "Locked") r.expire(f"{name}-{squad}-{environment}", settings.TASK_LOCKED_EXPIRED) # Git clone repo - result = tf.git_clone(git_repo, name, stack_name, - environment, squad, branch) - self.update_state(state='PULLING', meta={'done': "1 of 6"}) - if result['rc'] != 0: + result = tf.git_clone(git_repo, name, stack_name, environment, squad, branch) + self.update_state(state="PULLING", meta={"done": "1 of 6"}) + if result["rc"] != 0: raise Exception(result) # Download terrafom result = tf.binary_download(stack_name, environment, squad, version) - self.update_state(state='LOADBIN', meta={'done': "2 of 6"}) + self.update_state(state="LOADBIN", meta={"done": "2 of 6"}) # Delete artifactory to avoid duplicating the runner logs dir_path = f"/tmp/{ stack_name }/{environment}/{squad}/artifacts" tf.delete_local_folder(dir_path) - if result['rc'] != 0: + if result["rc"] != 0: raise Exception(result) # Create tf to use the custom artifactory as config - self.update_state(state='REMOTECONF', meta={'done': "3 of 6"}) + self.update_state(state="REMOTECONF", meta={"done": "3 of 6"}) result = tf.tfstate_render(stack_name, environment, squad, project_path, name) - if result['rc'] != 0: + if result["rc"] != 0: raise Exception(result) # Create tfvar serialize with json - self.update_state(state='SETVARS', meta={'done': "4 of 6"}) - result = tf.tfvars(stack_name, environment, squad, name, project_path, vars=kwargs) - if result['rc'] != 0: + self.update_state(state="SETVARS", meta={"done": "4 of 6"}) + result = tf.tfvars( + stack_name, environment, squad, name, project_path, vars=kwargs + ) + if result["rc"] != 0: raise Exception(result) # Plan execute - self.update_state(state='PLANNING', meta={'done': "5 of 6"}) - result = tf.plan_execute(stack_name, environment, - squad, name, version, variables_file, project_path, data=secreto) + self.update_state(state="PLANNING", meta={"done": "5 of 6"}) + result = tf.plan_execute( + stack_name, + environment, + squad, + name, + version, + variables_file, + project_path, + data=secreto, + ) # Delete artifactory to avoid duplicating the runner logs dir_path = f"/tmp/{ stack_name }/{environment}/{squad}/{name}/artifacts" tf.delete_local_folder(dir_path) - if result['rc'] != 0: + if result["rc"] != 0: raise Exception(result) # Apply execute - self.update_state(state='APPLYING', meta={'done': "6 of 6"}) + self.update_state(state="APPLYING", meta={"done": "6 of 6"}) result = tf.apply_execute( - stack_name, branch, environment, squad, name, version, variables_file, project_path, data=secreto) - if result['rc'] != 0: + stack_name, + branch, + environment, + squad, + name, + version, + variables_file, + project_path, + data=secreto, + ) + if result["rc"] != 0: raise Exception(result) return result except Exception as err: if not settings.ROLLBACK: - self.retry(countdown=settings.TASK_RETRY_INTERVAL, - exc=err, max_retries=settings.TASK_MAX_RETRY) - self.update_state(state=states.FAILURE, meta={'exc': result}) + self.retry( + countdown=settings.TASK_RETRY_INTERVAL, + exc=err, + max_retries=settings.TASK_MAX_RETRY, + ) + self.update_state(state=states.FAILURE, meta={"exc": result}) raise Ignore() - self.update_state(state="ROLLBACK", meta={'done': "1 of 1"}) + self.update_state(state="ROLLBACK", meta={"done": "1 of 1"}) destroy_eresult = tf.destroy_execute( - stack_name, environment, squad, name, version,variables_file, project_path, data=secreto) - self.update_state(state=states.FAILURE, meta={ - 'exc_type': type(err).__name__, - 'exc_message': traceback.format_exc().split('\n') - }) + stack_name, + environment, + squad, + name, + version, + variables_file, + project_path, + data=secreto, + ) + self.update_state( + state=states.FAILURE, + meta={ + "exc_type": type(err).__name__, + "exc_message": traceback.format_exc().split("\n"), + }, + ) raise Ignore() finally: dir_path = f"/tmp/{ stack_name }/{environment}/{squad}/{name}" @@ -94,60 +132,69 @@ def pipeline_deploy( tf.delete_local_folder(dir_path) -@celery_app.task(bind=True, acks_late=True, name='pipeline Destroy') +@celery_app.task(bind=True, acks_late=True, name="pipeline Destroy") def pipeline_destroy( - self, - git_repo: str, - name: str, - stack_name: str, - environment: str, - squad: str, - branch: str, - version: str, - kwargs: any, - secreto: str, - variables_file: str = "", - project_path: str = "" - ): - filter_kwargs = {key: value for ( - key, value) in kwargs.items() if "pass" not in key} + self, + git_repo: str, + name: str, + stack_name: str, + environment: str, + squad: str, + branch: str, + version: str, + kwargs: any, + secreto: str, + variables_file: str = "", + project_path: str = "", +): + filter_kwargs = {key: value for (key, value) in kwargs.items() if "pass" not in key} try: r.set(f"{name}-{squad}-{environment}", "Locked") r.expire(f"{name}-{squad}-{environment}", settings.TASK_LOCKED_EXPIRED) # Git clone repo - result = tf.git_clone(git_repo, name, stack_name, - environment, squad, branch) - self.update_state(state='PULLING', meta={'done': "1 of 6"}) - if result['rc'] != 0: + result = tf.git_clone(git_repo, name, stack_name, environment, squad, branch) + self.update_state(state="PULLING", meta={"done": "1 of 6"}) + if result["rc"] != 0: raise Exception(result) # Download terrafom result = tf.binary_download(stack_name, environment, squad, version) - self.update_state(state='LOADBIN', meta={'done': "2 of 6"}) + self.update_state(state="LOADBIN", meta={"done": "2 of 6"}) # Delete artifactory to avoid duplicating the runner logs dir_path = f"/tmp/{ stack_name }/{environment}/{squad}/artifacts" tf.delete_local_folder(dir_path) - if result['rc'] != 0: + if result["rc"] != 0: raise Exception(result) # Create tf to use the custom artifactory as config - self.update_state(state='REMOTECONF', meta={'done': "3 of 6"}) + self.update_state(state="REMOTECONF", meta={"done": "3 of 6"}) result = tf.tfstate_render(stack_name, environment, squad, project_path, name) - if result['rc'] != 0: + if result["rc"] != 0: raise Exception(result) # Create tfvar serialize with json - self.update_state(state='SETVARS', meta={'done': "4 of 6"}) - result = tf.tfvars(stack_name, environment, squad, name, project_path, vars=kwargs) - if result['rc'] != 0: + self.update_state(state="SETVARS", meta={"done": "4 of 6"}) + result = tf.tfvars( + stack_name, environment, squad, name, project_path, vars=kwargs + ) + if result["rc"] != 0: raise Exception(result) - self.update_state(state='DESTROYING', meta={'done': "6 of 6"}) + self.update_state(state="DESTROYING", meta={"done": "6 of 6"}) result = tf.destroy_execute( - stack_name, branch, environment, squad, name, version, variables_file, project_path, data=secreto) - if result['rc'] != 0: + stack_name, + branch, + environment, + squad, + name, + version, + variables_file, + project_path, + data=secreto, + ) + if result["rc"] != 0: raise Exception(result) return result except Exception as err: self.retry(countdown=5, exc=err, max_retries=1) - self.update_state(state=states.FAILURE, meta={'exc': result}) + self.update_state(state=states.FAILURE, meta={"exc": result}) raise Ignore() finally: dir_path = f"/tmp/{ stack_name }/{environment}/{squad}/{name}" @@ -155,134 +202,142 @@ def pipeline_destroy( r.delete(f"{name}-{squad}-{environment}") -@celery_app.task(bind=True, acks_late=True, name='pipeline Plan') +@celery_app.task(bind=True, acks_late=True, name="pipeline Plan") def pipeline_plan( - self, - git_repo: str, - name: str, - stack_name: str, - environment: str, - squad: str, - branch: str, - version: str, - kwargs: any, - secreto: str, - variables_file: str = "", - project_path: str = "" - ): - filter_kwargs = {key: value for ( - key, value) in kwargs.items() if "pass" not in key} + self, + git_repo: str, + name: str, + stack_name: str, + environment: str, + squad: str, + branch: str, + version: str, + kwargs: any, + secreto: str, + variables_file: str = "", + project_path: str = "", +): + filter_kwargs = {key: value for (key, value) in kwargs.items() if "pass" not in key} try: - self.update_state(state='GIT', meta={'done': "1 of 5"}) - result = tf.git_clone(git_repo, name, stack_name, - environment, squad, branch) - if result['rc'] != 0: + self.update_state(state="GIT", meta={"done": "1 of 5"}) + result = tf.git_clone(git_repo, name, stack_name, environment, squad, branch) + if result["rc"] != 0: raise Exception(result) - self.update_state(state='BINARY', meta={'done': "2 of 5"}) + self.update_state(state="BINARY", meta={"done": "2 of 5"}) result = tf.binary_download(stack_name, environment, squad, version) dir_path = f"/tmp/{ stack_name }/{environment}/{squad}/artifacts" tf.delete_local_folder(dir_path) - if result['rc'] != 0: + if result["rc"] != 0: raise Exception(result) - self.update_state(state='REMOTE', meta={'done': "3 of 5"}) + self.update_state(state="REMOTE", meta={"done": "3 of 5"}) result = tf.tfstate_render(stack_name, environment, squad, project_path, name) - if result['rc'] != 0: + if result["rc"] != 0: raise Exception(result) - self.update_state(state='VARS', meta={'done': "4 of 5"}) - result = tf.tfvars(stack_name, environment, squad, name, project_path, vars=kwargs) - if result['rc'] != 0: + self.update_state(state="VARS", meta={"done": "4 of 5"}) + result = tf.tfvars( + stack_name, environment, squad, name, project_path, vars=kwargs + ) + if result["rc"] != 0: raise Exception(result) - self.update_state(state='PLAN', meta={'done': "5 of 5"}) - result = tf.plan_execute(stack_name, environment, - squad, name, version, variables_file, project_path, data=secreto) + self.update_state(state="PLAN", meta={"done": "5 of 5"}) + result = tf.plan_execute( + stack_name, + environment, + squad, + name, + version, + variables_file, + project_path, + data=secreto, + ) dir_path = f"/tmp/{ stack_name }/{environment}/{squad}/{name}/artifacts" tf.delete_local_folder(dir_path) - if result['rc'] != 0: + if result["rc"] != 0: raise Exception(result) return result except Exception as err: self.retry(countdown=5, exc=err, max_retries=1) - self.update_state(state=states.FAILURE, meta={'exc': result}) + self.update_state(state=states.FAILURE, meta={"exc": result}) raise Ignore() finally: dir_path = f"/tmp/{ stack_name }/{environment}/{squad}/{name}" tf.delete_local_folder(dir_path) -@celery_app.task(bind=True, - acks_late=True, - time_limit=settings.GIT_TMOUT, - name='pipeline git pull') +@celery_app.task( + bind=True, acks_late=True, time_limit=settings.GIT_TMOUT, name="pipeline git pull" +) def pipeline_git_pull( - self, - git_repo: str, - name: str, - stack_name: str, - environment: str, - squad: str, - branch: str - ): + self, + git_repo: str, + name: str, + stack_name: str, + environment: str, + squad: str, + branch: str, +): try: - git_result = tf.git_clone(git_repo, name, stack_name, - environment, squad, branch) - if git_result['rc'] != 0: - raise Exception(result.get('stdout')) + git_result = tf.git_clone( + git_repo, name, stack_name, environment, squad, branch + ) + if git_result["rc"] != 0: + raise Exception(result.get("stdout")) - self.update_state(state='GET_VARS_AS_JSON', meta={'done': "2 of 2"}) + self.update_state(state="GET_VARS_AS_JSON", meta={"done": "2 of 2"}) result = tf.get_vars_json( - environment=environment, stack_name=stack_name, squad=squad, name=name) - if result['rc'] != 0: + environment=environment, stack_name=stack_name, squad=squad, name=name + ) + if result["rc"] != 0: raise Exception(result) result["tfvars"] = git_result["tfvars"] return result except Exception as err: - self.retry(countdown=settings.GIT_TMOUT, - exc=err, max_retries=settings.TASK_MAX_RETRY) - self.update_state(state=states.FAILURE, meta={'exc': result}) + self.retry( + countdown=settings.GIT_TMOUT, exc=err, max_retries=settings.TASK_MAX_RETRY + ) + self.update_state(state=states.FAILURE, meta={"exc": result}) raise Ignore() finally: dir_path = f"/tmp/artifacts" tf.delete_local_folder(dir_path) -@celery_app.task(bind=True, - acks_late=True, - time_limit=settings.GIT_TMOUT, - name='download git repo') +@celery_app.task( + bind=True, acks_late=True, time_limit=settings.GIT_TMOUT, name="download git repo" +) def git( - self, - git_repo: str, - name: str, - stack_name: str, - environment: str, - squad: str, - branch: str - ): + self, + git_repo: str, + name: str, + stack_name: str, + environment: str, + squad: str, + branch: str, +): try: - result = tf.git_clone(git_repo, name, stack_name, - environment, squad, branch) + result = tf.git_clone(git_repo, name, stack_name, environment, squad, branch) except Exception as err: - self.retry(countdown=settings.GIT_TMOUT, - exc=err, max_retries=settings.TASK_MAX_RETRY) - self.update_state(state=states.FAILURE, meta={'exc': result}) + self.retry( + countdown=settings.GIT_TMOUT, exc=err, max_retries=settings.TASK_MAX_RETRY + ) + self.update_state(state=states.FAILURE, meta={"exc": result}) raise Ignore() return stack_name, environment, squad, name, result -@celery_app.task(bind=True, acks_late=True, time_limit=settings.WORKER_TMOUT, max_retries=1, name='terraform output') -def output( - self, - stack_name: str, - environment: str, - squad: str, - name: str - ): +@celery_app.task( + bind=True, + acks_late=True, + time_limit=settings.WORKER_TMOUT, + max_retries=1, + name="terraform output", +) +def output(self, stack_name: str, environment: str, squad: str, name: str): try: - output_result = tf.output_execute( - stack_name, environment, squad, name) + output_result = tf.output_execute(stack_name, environment, squad, name) return output_result except Exception as err: return {"stdout": err} @@ -291,97 +346,104 @@ def output( tf.delete_local_folder(dir_path) -@celery_app.task(bind=True, acks_late=True, time_limit=settings.WORKER_TMOUT, max_retries=1, name='terraform unlock') -def unlock( - self, - stack_name: str, - environment: str, - squad: str, - name: str - ): +@celery_app.task( + bind=True, + acks_late=True, + time_limit=settings.WORKER_TMOUT, + max_retries=1, + name="terraform unlock", +) +def unlock(self, stack_name: str, environment: str, squad: str, name: str): try: - unlock_result = tf.unlock_execute( - stack_name, environment, squad, name) + unlock_result = tf.unlock_execute(stack_name, environment, squad, name) return unlock_result except Exception as err: return {"stdout": err} -@celery_app.task(bind=True, acks_late=True, time_limit=settings.WORKER_TMOUT, name='terraform show') -def show( - self, - stack_name: str, - environment: str, - squad: str, - name: str - ): - show_result = tf.show_execute( - stack_name, environment, squad, name) +@celery_app.task( + bind=True, acks_late=True, time_limit=settings.WORKER_TMOUT, name="terraform show" +) +def show(self, stack_name: str, environment: str, squad: str, name: str): + show_result = tf.show_execute(stack_name, environment, squad, name) return show_result -@celery_app.task(bind=True, acks_late=True, time_limit=settings.WORKER_TMOUT, name='schedules list') +@celery_app.task( + bind=True, acks_late=True, time_limit=settings.WORKER_TMOUT, name="schedules list" +) def schedules_list(self): try: - return request_url(verb='GET', uri=f'schedules/').get('json') - except Exception as err: + return request_url(verb="GET", uri=f"schedules/").get("json") + except Exception: pass -@celery_app.task(bind=True, acks_late=True, time_limit=settings.WORKER_TMOUT, name='schedule get') +@celery_app.task( + bind=True, acks_late=True, time_limit=settings.WORKER_TMOUT, name="schedule get" +) def schedule_get(self, deploy_name: str): try: - return request_url(verb='GET', uri=f'schedule/{deploy_name}').get('json') - except Exception as err: + return request_url(verb="GET", uri=f"schedule/{deploy_name}").get("json") + except Exception: pass -@celery_app.task(bind=True, acks_late=True, time_limit=settings.WORKER_TMOUT, name='schedule remove') +@celery_app.task( + bind=True, acks_late=True, time_limit=settings.WORKER_TMOUT, name="schedule remove" +) def schedule_delete(self, deploy_name: str): try: - return request_url(verb='DELETE', uri=f'schedule/{deploy_name}').get('json') - except Exception as err: + return request_url(verb="DELETE", uri=f"schedule/{deploy_name}").get("json") + except Exception: pass -@celery_app.task(bind=True, acks_late=True, time_limit=settings.WORKER_TMOUT, name='schedule add') +@celery_app.task( + bind=True, acks_late=True, time_limit=settings.WORKER_TMOUT, name="schedule add" +) def schedule_add(self, deploy_name: str): try: - return request_url(verb='POST', uri=f'schedule/{deploy_name}').get('json') + return request_url(verb="POST", uri=f"schedule/{deploy_name}").get("json") except Exception as err: return err -@celery_app.task(bind=True, acks_late=True, time_limit=settings.WORKER_TMOUT, max_retries=1, name='Update schedule') +@celery_app.task( + bind=True, + acks_late=True, + time_limit=settings.WORKER_TMOUT, + max_retries=1, + name="Update schedule", +) def schedule_update(self, deploy_name: str): try: - request_url(verb='DELETE', uri=f'schedule/{deploy_name}') - return request_url(verb='POST', uri=f'schedule/{deploy_name}').get('json') + request_url(verb="DELETE", uri=f"schedule/{deploy_name}") + return request_url(verb="POST", uri=f"schedule/{deploy_name}").get("json") except Exception as err: - logging.warning(request_url( - verb='POST', uri=f'schedule/{deploy_name}')) + logging.warning(request_url(verb="POST", uri=f"schedule/{deploy_name}")) return err -@celery_app.task(bind=True, acks_late=True, name='delete local module stack ') +@celery_app.task(bind=True, acks_late=True, name="delete local module stack ") def delete_local_stack(self, environment: str, squad: str, args: any): result = tf.delete_local_repo(environment, squad, args) return result -@celery_app.task(bind=True, acks_late=True, name='get variables list') +@celery_app.task(bind=True, acks_late=True, name="get variables list") def get_variable_list(self, environment: str, stack_name: str, squad: str, name: str): result = tf.get_vars_list(environment, stack_name, squad, name) return result -@celery_app.task(bind=True, acks_late=True, name='get variables json') +@celery_app.task(bind=True, acks_late=True, name="get variables json") def get_variable_json(self, environment: str, stack_name: str, squad: str, name: str): result = tf.get_vars_json(environment, stack_name, squad, name) return result -@celery_app.task(bind=True, acks_late=True, name='get variables from tfvars') +@celery_app.task(bind=True, acks_late=True, name="get variables from tfvars") def get_tfvars(self, environment: str, stack_name: str, squad: str, name: str): result = tf.get_vars_tfvars(environment, stack_name, squad, name) return result diff --git a/sld-api-backend/test/config/api.py b/sld-api-backend/test/config/api.py index 8422c06b..122bc641 100644 --- a/sld-api-backend/test/config/api.py +++ b/sld-api-backend/test/config/api.py @@ -4,9 +4,9 @@ class Settings(BaseSettings): - SERVER: str = 'http://localhost' - PORT: str = '8000' - API: str = '/api/v1' + SERVER: str = "http://localhost" + PORT: str = "8000" + API: str = "/api/v1" USER_SCHEDULE: str = "schedule" USER_SCHEDULEC: str = "Schedule1@local" USER_ADM: str = "admin" @@ -21,25 +21,11 @@ class Settings(BaseSettings): STACK_NAME_GCP: str = "gcp_vpc" GIT_REPO_AWS: str = "https://gitlab.com/hernand/aws_vpc_tf.git" GIT_REPO_GCP: str = "https://gitlab.com/hernand/aws_gcloud_tf.git" - INIT_CREDENTIALS: dict = { - "password": PASS_ADM - } - CREDENTIALS_ADM: dict = { - "username": USER_ADM, - "password": PASS_ADM - } - CREDENTIALS_ADM_SQUAD: dict = { - "username": USER_PRIV, - "password": PASS_USER - } - CREDENTIALS_BAD_PASSWD: dict = { - "username": USER_ADM, - "password": "bad_password" - } - CREDENTIALS_USER: dict = { - "username": USER_01, - "password": PASS_USER - } + INIT_CREDENTIALS: dict = {"password": PASS_ADM} + CREDENTIALS_ADM: dict = {"username": USER_ADM, "password": PASS_ADM} + CREDENTIALS_ADM_SQUAD: dict = {"username": USER_PRIV, "password": PASS_USER} + CREDENTIALS_BAD_PASSWD: dict = {"username": USER_ADM, "password": "bad_password"} + CREDENTIALS_USER: dict = {"username": USER_01, "password": PASS_USER} USER_PATCH: dict = { "username": "", "fullname": "", @@ -47,7 +33,7 @@ class Settings(BaseSettings): "email": "admin@example.com", "role": ["yoda"], "squad": ["*"], - "is_active": True + "is_active": True, } USER_POST: dict = { "username": USER_TEST, @@ -56,7 +42,7 @@ class Settings(BaseSettings): "email": "test01@example.com", "role": ["stormtrooper", "R2-D2"], "squad": ["squad1"], - "is_active": True + "is_active": True, } USER_POST_SQUAD1: dict = { "username": USER_01, @@ -65,7 +51,7 @@ class Settings(BaseSettings): "email": "user01@example.com", "role": ["stormtrooper"], "squad": ["squad1"], - "is_active": True + "is_active": True, } USER_POST_SQUAD2: dict = { "username": USER_02, @@ -74,7 +60,7 @@ class Settings(BaseSettings): "email": "user02@example.com", "role": ["stormtrooper"], "squad": ["squad2"], - "is_active": True + "is_active": True, } USER_POST_PRIV: dict = { "username": USER_PRIV, @@ -82,8 +68,8 @@ class Settings(BaseSettings): "password": PASS_USER, "email": "admin_squad@example.com", "role": ["darth_vader"], - "squad": ["squad1","squad2"], - "is_active": True + "squad": ["squad1", "squad2"], + "is_active": True, } USER_POST_OFF: dict = { "username": USER_OFF, @@ -92,7 +78,7 @@ class Settings(BaseSettings): "email": "user_off@example.com", "role": ["darth_vader"], "squad": ["squad1"], - "is_active": False + "is_active": False, } USER_SCHEDULE: dict = { "username": USER_SCHEDULE, @@ -101,7 +87,7 @@ class Settings(BaseSettings): "email": "schedule@example.com", "role": ["yoda", "R2-D2"], "squad": ["*"], - "is_active": True + "is_active": True, } STACK_POST_AWS: dict = { "stack_name": STACK_NAME_AWS, @@ -109,7 +95,7 @@ class Settings(BaseSettings): "squad_access": ["*"], "branch": "master", "description": STACK_NAME_AWS, - "tf_version": "1.0.7" + "tf_version": "1.0.7", } STACK_POST_GCP: dict = { "stack_name": STACK_NAME_GCP, @@ -117,49 +103,49 @@ class Settings(BaseSettings): "branch": "master", "squad_access": ["*"], "description": STACK_NAME_GCP, - "tf_version": "0.14.1" + "tf_version": "0.14.1", } AWS_TEST_ACCOUNT: dict = { "squad": "squad1", "environment": "develop", - "access_key_id": os.getenv('AWS_ACCESS_KEY_ID'), - "secret_access_key": os.getenv('AWS_SECRET_ACCESS_KEY'), + "access_key_id": os.getenv("AWS_ACCESS_KEY_ID"), + "secret_access_key": os.getenv("AWS_SECRET_ACCESS_KEY"), "default_region": "eu-west-1", "profile_name": "string", "role_arn": "string", - "source_profile": "string" + "source_profile": "string", } AWS_TEST_ACCOUNT_PRO: dict = { "squad": "squad1", "environment": "pro", - "access_key_id": os.getenv('AWS_ACCESS_KEY_ID'), - "secret_access_key": os.getenv('AWS_SECRET_ACCESS_KEY'), + "access_key_id": os.getenv("AWS_ACCESS_KEY_ID"), + "secret_access_key": os.getenv("AWS_SECRET_ACCESS_KEY"), "default_region": "eu-west-1", "profile_name": "string", "role_arn": "string", - "source_profile": "string" + "source_profile": "string", } AWS_TEST_ACCOUNT_SQUAD2: dict = { "squad": "squad2", "environment": "develop", - "access_key_id": os.getenv('AWS_ACCESS_KEY_ID'), - "secret_access_key": os.getenv('AWS_SECRET_ACCESS_KEY'), + "access_key_id": os.getenv("AWS_ACCESS_KEY_ID"), + "secret_access_key": os.getenv("AWS_SECRET_ACCESS_KEY"), "default_region": "eu-west-1", "profile_name": "string", "role_arn": "string", - "source_profile": "string" + "source_profile": "string", } AWS_TEST_ACCOUNT_SQUAD2_PRO: dict = { "squad": "squad2", "environment": "pro", - "access_key_id": os.getenv('AWS_ACCESS_KEY_ID'), - "secret_access_key": os.getenv('AWS_SECRET_ACCESS_KEY'), + "access_key_id": os.getenv("AWS_ACCESS_KEY_ID"), + "secret_access_key": os.getenv("AWS_SECRET_ACCESS_KEY"), "default_region": "eu-west-1", "profile_name": "string", "role_arn": "string", - "source_profile": "string" + "source_profile": "string", } - DEPLOY_URI: str = '?tf_ver=1.0.7' + DEPLOY_URI: str = "?tf_ver=1.0.7" DEPLOY_VARS: dict = { "name": "aws_vpc_darth_vader", "stack_name": "aws_vpc", @@ -174,20 +160,12 @@ class Settings(BaseSettings): "be1": "19.0.0.0/24", "be2": "19.0.1.0/24", "fe1": "19.0.2.0/24", - "fe2": "19.0.3.0/24" + "fe2": "19.0.3.0/24", }, - "availability_zone_names": [ - "eu-west-1" - ], - "docker_ports": [ - { - "internal": 8999, - "external": 1111, - "protocol": "udp" - } - ], - "password": "PassWW" - } + "availability_zone_names": ["eu-west-1"], + "docker_ports": [{"internal": 8999, "external": 1111, "protocol": "udp"}], + "password": "PassWW", + }, } DEPLOY_VARS_USER: dict = { "name": "aws_vpc_stormtrooper", @@ -203,20 +181,12 @@ class Settings(BaseSettings): "be1": "19.0.0.0/24", "be2": "19.0.1.0/24", "fe1": "19.0.2.0/24", - "fe2": "19.0.3.0/24" + "fe2": "19.0.3.0/24", }, - "availability_zone_names": [ - "eu-west-1" - ], - "docker_ports": [ - { - "internal": 8999, - "external": 1111, - "protocol": "udp" - } - ], - "password": "Password" - } + "availability_zone_names": ["eu-west-1"], + "docker_ports": [{"internal": 8999, "external": 1111, "protocol": "udp"}], + "password": "Password", + }, } DEPLOY_VARS_MASTER: dict = { "name": "aws_vpc_yoda", @@ -226,25 +196,17 @@ class Settings(BaseSettings): "start_time": "*/5 * * * *", "destroy_time": "*/7 * * * *", "variables": { - "vpc_cidr": "11.0.0.0/16", - "subnet_cidr": { - "be1": "11.0.0.0/24", - "be2": "11.0.1.0/24", - "fe1": "11.0.2.0/24", - "fe2": "11.0.3.0/24" - }, - "availability_zone_names": [ - "eu-west-1" - ], - "docker_ports": [ - { - "internal": 8300, - "external": 8300, - "protocol": "tcp" - } - ], - "password": "PasswordAdmin" - } + "vpc_cidr": "11.0.0.0/16", + "subnet_cidr": { + "be1": "11.0.0.0/24", + "be2": "11.0.1.0/24", + "fe1": "11.0.2.0/24", + "fe2": "11.0.3.0/24", + }, + "availability_zone_names": ["eu-west-1"], + "docker_ports": [{"internal": 8300, "external": 8300, "protocol": "tcp"}], + "password": "PasswordAdmin", + }, } DEPLOY_VARS_UPDATE: dict = { "name": "aws_vpc_yoda", @@ -254,25 +216,18 @@ class Settings(BaseSettings): "start_time": "*/5 * * * *", "destroy_time": "*/7 * * * *", "variables": { - "vpc_cidr": "11.0.0.0/16", - "subnet_cidr": { - "be1": "11.0.0.0/24", - "be2": "11.0.1.0/24", - "fe1": "11.0.2.0/24", - "fe2": "11.0.3.0/24" - }, - "availability_zone_names": [ - "eu-west-1" - ], - "docker_ports": [ - { - "internal": 8300, - "external": 8300, - "protocol": "tcp" - } - ], - "password": "Pass123" - } + "vpc_cidr": "11.0.0.0/16", + "subnet_cidr": { + "be1": "11.0.0.0/24", + "be2": "11.0.1.0/24", + "fe1": "11.0.2.0/24", + "fe2": "11.0.3.0/24", + }, + "availability_zone_names": ["eu-west-1"], + "docker_ports": [{"internal": 8300, "external": 8300, "protocol": "tcp"}], + "password": "Pass123", + }, } + settings = Settings() diff --git a/sld-api-backend/test/helpers/api_request.py b/sld-api-backend/test/helpers/api_request.py index f8f36a77..cd5c9243 100644 --- a/sld-api-backend/test/helpers/api_request.py +++ b/sld-api-backend/test/helpers/api_request.py @@ -6,24 +6,22 @@ api = settings.API -def request_url(verb: str, headers: dict = '', uri: str = '', json: dict = ''): +def request_url(verb: str, headers: dict = "", uri: str = "", json: dict = ""): response = requests.request( - verb, - headers=headers, - url=f'{server}:{port}{api}/{uri}', - json=json + verb, headers=headers, url=f"{server}:{port}{api}/{uri}", json=json ) - result = {'status_code': response.status_code, - 'content': response.content.decode('utf-8'), - 'json': response.json() - } + result = { + "status_code": response.status_code, + "content": response.content.decode("utf-8"), + "json": response.json(), + } return result def check_status(): - response = request_url(verb='GET') + response = request_url(verb="GET") return response -if __name__ == '__main__': +if __name__ == "__main__": print(check_status()) diff --git a/sld-api-backend/test/helpers/api_token.py b/sld-api-backend/test/helpers/api_token.py index a1eca457..8ff00a59 100644 --- a/sld-api-backend/test/helpers/api_token.py +++ b/sld-api-backend/test/helpers/api_token.py @@ -1,17 +1,17 @@ -from helpers.api_request import request_url from config.api import settings +from helpers.api_request import request_url def get_token(data): response = request_url( - verb='POST', - headers={'Content-Type': 'application/json'}, - uri='authenticate/access-token-json', - json=data + verb="POST", + headers={"Content-Type": "application/json"}, + uri="authenticate/access-token-json", + json=data, ) - if response.get('status_code') == 200: - result = response.get('json') - return result.get('access_token') + if response.get("status_code") == 200: + result = response.get("json") + return result.get("access_token") if __name__ == "__main__": diff --git a/sld-api-backend/test/test_00_user_init.py b/sld-api-backend/test/test_00_user_init.py index 853c12e5..5f8fa84e 100644 --- a/sld-api-backend/test/test_00_user_init.py +++ b/sld-api-backend/test/test_00_user_init.py @@ -1,16 +1,16 @@ -from helpers.api_request import request_url from config.api import settings +from helpers.api_request import request_url def test_check_status_code_equals_200(): - response = request_url(verb='GET') - assert response.get('status_code') == 200 - assert response.get('json') == {'status': 'healthy'} + response = request_url(verb="GET") + assert response.get("status_code") == 200 + assert response.get("json") == {"status": "healthy"} def test_create_user_init(): data = settings.INIT_CREDENTIALS - response = request_url(verb='POST', uri='users/start', json=data) - result = response.get('status_code') + response = request_url(verb="POST", uri="users/start", json=data) + result = response.get("status_code") if result != 409: - assert response.get('status_code') == 200 + assert response.get("status_code") == 200 diff --git a/sld-api-backend/test/test_01_crud_users.py b/sld-api-backend/test/test_01_crud_users.py index cd5beef9..972f7090 100644 --- a/sld-api-backend/test/test_01_crud_users.py +++ b/sld-api-backend/test/test_01_crud_users.py @@ -1,6 +1,6 @@ +from config.api import settings from helpers.api_request import request_url from helpers.api_token import get_token -from config.api import settings token = get_token(settings.CREDENTIALS_ADM) token_unprivileges = get_token(settings.CREDENTIALS_USER) @@ -10,80 +10,112 @@ def test_update_user_init(): data = settings.USER_PATCH - list_user = request_url(verb='GET', uri=f'users/{user_adm}', headers={ - "Authorization": f"Bearer {token}"}) + list_user = request_url( + verb="GET", + uri=f"users/{user_adm}", + headers={"Authorization": f"Bearer {token}"}, + ) id = list_user.get("json").get("id") - response = request_url(verb='PATCH', uri=f'users/{id}', headers={ - "Authorization": f"Bearer {token}"}, json=data) - assert response.get('status_code') == 200 + response = request_url( + verb="PATCH", + uri=f"users/{id}", + headers={"Authorization": f"Bearer {token}"}, + json=data, + ) + assert response.get("status_code") == 200 def test_list_users(): - response = request_url(verb='GET', uri='users/?limit=1', headers={ - "Authorization": f"Bearer {token}"}) - assert response.get('status_code') == 200 + response = request_url( + verb="GET", uri="users/?limit=1", headers={"Authorization": f"Bearer {token}"} + ) + assert response.get("status_code") == 200 def test_users_with_bad_passwd(): response = request_url( - verb='POST', - headers={'Content-Type': 'application/json'}, - uri='authenticate/access-token-json', - json=settings.CREDENTIALS_BAD_PASSWD + verb="POST", + headers={"Content-Type": "application/json"}, + uri="authenticate/access-token-json", + json=settings.CREDENTIALS_BAD_PASSWD, ) - assert response.get('status_code') == 403 + assert response.get("status_code") == 403 def test_create_unprivilege_user(): data = settings.USER_POST - response = request_url(verb='POST', uri='users/', headers={ - "Authorization": f"Bearer {token}"}, json=data) - result = response.get('status_code') + response = request_url( + verb="POST", + uri="users/", + headers={"Authorization": f"Bearer {token}"}, + json=data, + ) + result = response.get("status_code") if result != 409: assert result == 200 def test_create_unprivilege_user_squad1(): data = settings.USER_POST_SQUAD1 - response = request_url(verb='POST', uri='users/', headers={ - "Authorization": f"Bearer {token}"}, json=data) - result = response.get('status_code') + response = request_url( + verb="POST", + uri="users/", + headers={"Authorization": f"Bearer {token}"}, + json=data, + ) + result = response.get("status_code") if result != 400: assert result == 200 def test_create_unprivilege_user_squad2(): data = settings.USER_POST_SQUAD2 - response = request_url(verb='POST', uri='users/', headers={ - "Authorization": f"Bearer {token}"}, json=data) - result = response.get('status_code') + response = request_url( + verb="POST", + uri="users/", + headers={"Authorization": f"Bearer {token}"}, + json=data, + ) + result = response.get("status_code") if result != 400: assert result == 200 def test_create_privilege_user_squad1(): data = settings.USER_POST_PRIV - response = request_url(verb='POST', uri='users/', headers={ - "Authorization": f"Bearer {token}"}, json=data) - result = response.get('status_code') + response = request_url( + verb="POST", + uri="users/", + headers={"Authorization": f"Bearer {token}"}, + json=data, + ) + result = response.get("status_code") if result != 400: assert result == 200 def test_create_bot_user(): data = settings.USER_SCHEDULE - response = request_url(verb='POST', uri='users/', headers={ - "Authorization": f"Bearer {token}"}, json=data) - result = response.get('status_code') + response = request_url( + verb="POST", + uri="users/", + headers={"Authorization": f"Bearer {token}"}, + json=data, + ) + result = response.get("status_code") if result != 400: assert result == 200 def test_create_unprivilege_user_disable(): data = settings.USER_POST_OFF - response = request_url(verb='POST', uri='users/', headers={ - "Authorization": f"Bearer {token}"}, json=data) - result = response.get('status_code') + response = request_url( + verb="POST", + uri="users/", + headers={"Authorization": f"Bearer {token}"}, + json=data, + ) + result = response.get("status_code") if result != 400: assert result == 200 @@ -92,58 +124,61 @@ def test_try_create_user_as_unprivilege_user(): token_unprivileges = get_token(settings.CREDENTIALS_USER) data = settings.USER_POST response = request_url( - verb='POST', - uri='users/', - headers={ - "Authorization": f"Bearer {token_unprivileges}"}, - json=data) - result = response.get('status_code') + verb="POST", + uri="users/", + headers={"Authorization": f"Bearer {token_unprivileges}"}, + json=data, + ) + result = response.get("status_code") assert result == 403 def test_try_create_user_as_not_authenticated_user(): data = settings.USER_POST - response = request_url(verb='POST', uri='users/', json=data) - result = response.get('status_code') + response = request_url(verb="POST", uri="users/", json=data) + result = response.get("status_code") assert result == 401 def test_try_list_users_as_unprivileges_user(): token_unprivileges = get_token(settings.CREDENTIALS_USER) - response = request_url(verb='GET', uri='users/?limit=1', headers={ - "Authorization": f"Bearer {token_unprivileges}"}) - assert response.get('status_code') == 403 + response = request_url( + verb="GET", + uri="users/?limit=1", + headers={"Authorization": f"Bearer {token_unprivileges}"}, + ) + assert response.get("status_code") == 403 def test_try_list_users_as_not_authenticated_user(): - response = request_url(verb='GET', uri='users/?limit=1') - assert response.get('status_code') == 401 + response = request_url(verb="GET", uri="users/?limit=1") + assert response.get("status_code") == 401 def test_try_delete_user_as_unprivileges_user(): token_unprivileges = get_token(settings.CREDENTIALS_USER) list_user = request_url( - verb='GET', - uri=f'users/{user_test}', - headers={ - "Authorization": f"Bearer {token_unprivileges}" - } + verb="GET", + uri=f"users/{user_test}", + headers={"Authorization": f"Bearer {token_unprivileges}"}, ) id = list_user.get("json").get("id") response = request_url( - verb='DELETE', - uri=f'users/{id}', - headers={ - "Authorization": f"Bearer {token_unprivileges}" - } + verb="DELETE", + uri=f"users/{id}", + headers={"Authorization": f"Bearer {token_unprivileges}"}, ) - assert response.get('status_code') == 403 + assert response.get("status_code") == 403 def test_delete_user_test(): - list_user = request_url(verb='GET', uri=f'users/{user_test}', headers={ - "Authorization": f"Bearer {token}"}) + list_user = request_url( + verb="GET", + uri=f"users/{user_test}", + headers={"Authorization": f"Bearer {token}"}, + ) id = list_user.get("json").get("id") - response = request_url(verb='DELETE', uri=f'users/{id}', headers={ - "Authorization": f"Bearer {token}"}) - assert response.get('status_code') == 200 + response = request_url( + verb="DELETE", uri=f"users/{id}", headers={"Authorization": f"Bearer {token}"} + ) + assert response.get("status_code") == 200 diff --git a/sld-api-backend/test/test_02_crud_stacks.py b/sld-api-backend/test/test_02_crud_stacks.py index 2f602c6d..54d5814d 100644 --- a/sld-api-backend/test/test_02_crud_stacks.py +++ b/sld-api-backend/test/test_02_crud_stacks.py @@ -1,6 +1,6 @@ +from config.api import settings from helpers.api_request import request_url from helpers.api_token import get_token -from config.api import settings token = get_token(settings.CREDENTIALS_ADM) token_unprivileges = get_token(settings.CREDENTIALS_USER) @@ -11,92 +11,130 @@ def test_create_stack_aws(): - response = request_url(verb='POST', uri='stacks/', headers={ - "Authorization": f"Bearer {token}"}, json=aws_data) - result = response.get('status_code') + response = request_url( + verb="POST", + uri="stacks/", + headers={"Authorization": f"Bearer {token}"}, + json=aws_data, + ) + result = response.get("status_code") if result != 409: assert result == 200 + def test_create_stack_gcp(): - response = request_url(verb='POST', uri='stacks/', headers={ - "Authorization": f"Bearer {token}"}, json=gcp_data) - result = response.get('status_code') + response = request_url( + verb="POST", + uri="stacks/", + headers={"Authorization": f"Bearer {token}"}, + json=gcp_data, + ) + result = response.get("status_code") if result != 409: assert result == 200 def test_try_create_stack_as_unprivilege_user(): response = request_url( - verb='POST', - uri='stacks/', - headers={ - "Authorization": f"Bearer {token_unprivileges}"}, - json=aws_data) - result = response.get('status_code') + verb="POST", + uri="stacks/", + headers={"Authorization": f"Bearer {token_unprivileges}"}, + json=aws_data, + ) + result = response.get("status_code") assert result == 403 def test_try_create_stack_as_not_authenticated_user(): response = request_url( - verb='POST', - uri='stacks/', - headers={ - "Authorization": f"Bearer {token_unprivileges}"}, - json=aws_data) - result = response.get('status_code') + verb="POST", + uri="stacks/", + headers={"Authorization": f"Bearer {token_unprivileges}"}, + json=aws_data, + ) + result = response.get("status_code") assert result == 403 def test_list_stack_by_name(): - response = request_url(verb='GET', uri=f'stacks/{aws_stack_name}', headers={ - "Authorization": f"Bearer {token}"}) - result = response.get('status_code') + response = request_url( + verb="GET", + uri=f"stacks/{aws_stack_name}", + headers={"Authorization": f"Bearer {token}"}, + ) + result = response.get("status_code") assert result == 200 def test_try_list_stack_by_name_as_unprivilege_user(): - response = request_url(verb='GET', uri=f'stacks/{aws_stack_name}', headers={ - "Authorization": f"Bearer {token_unprivileges}"}) - result = response.get('status_code') + response = request_url( + verb="GET", + uri=f"stacks/{aws_stack_name}", + headers={"Authorization": f"Bearer {token_unprivileges}"}, + ) + result = response.get("status_code") assert result == 200 def test_delete_stack_by_name(): - response = request_url(verb='DELETE', uri=f'stacks/{aws_stack_name}', headers={ - "Authorization": f"Bearer {token}"}) - assert response.get('status_code') == 200 + response = request_url( + verb="DELETE", + uri=f"stacks/{aws_stack_name}", + headers={"Authorization": f"Bearer {token}"}, + ) + assert response.get("status_code") == 200 def test_create_stack_for_test_by_id(): - response = request_url(verb='POST', uri='stacks/', headers={ - "Authorization": f"Bearer {token}"}, json=aws_data) - result = response.get('status_code') + response = request_url( + verb="POST", + uri="stacks/", + headers={"Authorization": f"Bearer {token}"}, + json=aws_data, + ) + result = response.get("status_code") if result != 409: assert result == 200 def test_list_stack_by_id(): - response = request_url(verb='GET', uri=f'stacks/{aws_stack_name}', headers={ - "Authorization": f"Bearer {token}"}) + response = request_url( + verb="GET", + uri=f"stacks/{aws_stack_name}", + headers={"Authorization": f"Bearer {token}"}, + ) stack_id = response.get("json").get("id") - response = request_url(verb='GET', uri=f'stacks/{stack_id}', headers={ - "Authorization": f"Bearer {token}"}) - result = response.get('status_code') + response = request_url( + verb="GET", + uri=f"stacks/{stack_id}", + headers={"Authorization": f"Bearer {token}"}, + ) + result = response.get("status_code") assert result == 200 def test_delete_stack_by_id(): - response = request_url(verb='GET', uri=f'stacks/{aws_stack_name}', headers={ - "Authorization": f"Bearer {token}"}) + response = request_url( + verb="GET", + uri=f"stacks/{aws_stack_name}", + headers={"Authorization": f"Bearer {token}"}, + ) stack_id = response.get("json").get("id") - response = request_url(verb='DELETE', uri=f'stacks/{stack_id}', headers={ - "Authorization": f"Bearer {token}"}) - assert response.get('status_code') == 200 + response = request_url( + verb="DELETE", + uri=f"stacks/{stack_id}", + headers={"Authorization": f"Bearer {token}"}, + ) + assert response.get("status_code") == 200 def test_create_stack_aws_for_poc(): - response = request_url(verb='POST', uri='stacks/', headers={ - "Authorization": f"Bearer {token}"}, json=aws_data) - result = response.get('status_code') + response = request_url( + verb="POST", + uri="stacks/", + headers={"Authorization": f"Bearer {token}"}, + json=aws_data, + ) + result = response.get("status_code") if result != 409: assert result == 200 diff --git a/sld-api-backend/test/test_03_get_variables.py b/sld-api-backend/test/test_03_get_variables.py index 0984fdd6..a68ac179 100644 --- a/sld-api-backend/test/test_03_get_variables.py +++ b/sld-api-backend/test/test_03_get_variables.py @@ -1,6 +1,6 @@ +from config.api import settings from helpers.api_request import request_url from helpers.api_token import get_token -from config.api import settings token = get_token(settings.CREDENTIALS_ADM) token_unprivileges = get_token(settings.CREDENTIALS_USER) @@ -9,52 +9,66 @@ def test_create_stack_for_test_by_name(): - response = request_url(verb='POST', uri='stacks/', headers={ - "Authorization": f"Bearer {token}"}, json=data) - result = response.get('status_code') + response = request_url( + verb="POST", + uri="stacks/", + headers={"Authorization": f"Bearer {token}"}, + json=data, + ) + result = response.get("status_code") if result != 409: assert result == 200 def test_variables_stack_list_by_id(): - response = request_url(verb='GET', uri=f'stacks/{stack_name}', headers={ - "Authorization": f"Bearer {token}"}) + response = request_url( + verb="GET", + uri=f"stacks/{stack_name}", + headers={"Authorization": f"Bearer {token}"}, + ) stack_id = response.get("json").get("id") response = request_url( - verb='GET', - uri=f'variables/list?stack={stack_id}', - headers={ - "Authorization": f"Bearer {token}"}) - result = response.get('status_code') + verb="GET", + uri=f"variables/list?stack={stack_id}", + headers={"Authorization": f"Bearer {token}"}, + ) + result = response.get("status_code") assert result == 200 def test_variables_stack_list_by_name(): response = request_url( - verb='GET', uri=f'variables/list?stack={stack_name}', headers={ - "Authorization": f"Bearer {token}"}) - result = response.get('status_code') + verb="GET", + uri=f"variables/list?stack={stack_name}", + headers={"Authorization": f"Bearer {token}"}, + ) + result = response.get("status_code") assert result == 200 def test_variables_stack_json_by_id(): - response = request_url(verb='GET', uri=f'stacks/{stack_name}', headers={ - "Authorization": f"Bearer {token}"}) + response = request_url( + verb="GET", + uri=f"stacks/{stack_name}", + headers={"Authorization": f"Bearer {token}"}, + ) stack_id = response.get("json").get("id") response = request_url( - verb='GET', - uri=f'variables/json?stack={stack_id}', - headers={ - "Authorization": f"Bearer {token}"}) - result = response.get('status_code') + verb="GET", + uri=f"variables/json?stack={stack_id}", + headers={"Authorization": f"Bearer {token}"}, + ) + result = response.get("status_code") assert result == 200 def test_variables_stack_json_by_name(): response = request_url( - verb='GET', uri=f'variables/json?stack={stack_name}', headers={ - "Authorization": f"Bearer {token}"}) - result = response.get('status_code') + verb="GET", + uri=f"variables/json?stack={stack_name}", + headers={"Authorization": f"Bearer {token}"}, + ) + result = response.get("status_code") assert result == 200 diff --git a/sld-api-backend/test/test_04_crud_cloudAccounts.py b/sld-api-backend/test/test_04_crud_cloudAccounts.py index 4534c49b..273a12e6 100644 --- a/sld-api-backend/test/test_04_crud_cloudAccounts.py +++ b/sld-api-backend/test/test_04_crud_cloudAccounts.py @@ -1,6 +1,6 @@ +from config.api import settings from helpers.api_request import request_url from helpers.api_token import get_token -from config.api import settings token = get_token(settings.CREDENTIALS_ADM) token_unprivileges = get_token(settings.CREDENTIALS_USER) @@ -12,39 +12,59 @@ def test_create_aws_account(): - response = request_url(verb='POST', uri='accounts/aws', headers={ - "Authorization": f"Bearer {token}"}, json=data) - result = response.get('status_code') + response = request_url( + verb="POST", + uri="accounts/aws", + headers={"Authorization": f"Bearer {token}"}, + json=data, + ) + result = response.get("status_code") if result != 409: assert result == 200 def test_create_aws_account_pro_env(): - response = request_url(verb='POST', uri='accounts/aws', headers={ - "Authorization": f"Bearer {token}"}, json=data_pro) - result = response.get('status_code') + response = request_url( + verb="POST", + uri="accounts/aws", + headers={"Authorization": f"Bearer {token}"}, + json=data_pro, + ) + result = response.get("status_code") if result != 409: assert result == 200 def test_create_aws_account_squad2(): - response = request_url(verb='POST', uri='accounts/aws', headers={ - "Authorization": f"Bearer {token}"}, json=data_squad2) - result = response.get('status_code') + response = request_url( + verb="POST", + uri="accounts/aws", + headers={"Authorization": f"Bearer {token}"}, + json=data_squad2, + ) + result = response.get("status_code") if result != 409: assert result == 200 def test_create_aws_account_squad2_pro(): - response = request_url(verb='POST', uri='accounts/aws', headers={ - "Authorization": f"Bearer {token}"}, json=data_squad2_pro) - result = response.get('status_code') + response = request_url( + verb="POST", + uri="accounts/aws", + headers={"Authorization": f"Bearer {token}"}, + json=data_squad2_pro, + ) + result = response.get("status_code") if result != 409: assert result == 200 def test_get_aws_account(): - response = request_url(verb='GET', uri='accounts/aws', headers={ - "Authorization": f"Bearer {token}"}, json=data) - result = response.get('status_code') + response = request_url( + verb="GET", + uri="accounts/aws", + headers={"Authorization": f"Bearer {token}"}, + json=data, + ) + result = response.get("status_code") assert result == 200 diff --git a/sld-api-backend/test/test_05_crud_deploy.py b/sld-api-backend/test/test_05_crud_deploy.py index 92d3dfda..631a1614 100644 --- a/sld-api-backend/test/test_05_crud_deploy.py +++ b/sld-api-backend/test/test_05_crud_deploy.py @@ -1,7 +1,8 @@ +import time + +from config.api import settings from helpers.api_request import request_url from helpers.api_token import get_token -from config.api import settings -import time token = get_token(settings.CREDENTIALS_ADM) token_user_squad = get_token(settings.CREDENTIALS_ADM_SQUAD) @@ -16,110 +17,129 @@ def get_task_id(task_id): response = request_url( - verb='GET', - uri=f'tasks/id/{task_id}', - headers={ - "Authorization": f"Bearer {token}"}) + verb="GET", + uri=f"tasks/id/{task_id}", + headers={"Authorization": f"Bearer {token}"}, + ) return response def test_deploy_stack_stormtrooper(): - response = request_url(verb='POST', uri=f'deploy/{uri}', headers={ - "Authorization": f"Bearer {token_unprivileges}"}, json=data_user) - if response.get('status_code') != 409: - task_id = response.get('json').get('task').get('task_id') - while get_task_id(task_id).get('json').get( - 'result').get('state') != 'SUCCESS': + response = request_url( + verb="POST", + uri=f"deploy/{uri}", + headers={"Authorization": f"Bearer {token_unprivileges}"}, + json=data_user, + ) + if response.get("status_code") != 409: + task_id = response.get("json").get("task").get("task_id") + while get_task_id(task_id).get("json").get("result").get("state") != "SUCCESS": time.sleep(3) - result = response.get('status_code') + result = response.get("status_code") assert result == 202 - assert response.get('status_code') + assert response.get("status_code") def test_deploy_stack_darth_vader(): - response = request_url(verb='POST', uri=f'deploy/{uri}', headers={ - "Authorization": f"Bearer {token_user_squad}"}, json=data) - if response.get('status_code') != 409: - task_id = response.get('json').get('task').get('task_id') - while get_task_id(task_id).get('json').get( - 'result').get('state') != 'SUCCESS': + response = request_url( + verb="POST", + uri=f"deploy/{uri}", + headers={"Authorization": f"Bearer {token_user_squad}"}, + json=data, + ) + if response.get("status_code") != 409: + task_id = response.get("json").get("task").get("task_id") + while get_task_id(task_id).get("json").get("result").get("state") != "SUCCESS": time.sleep(3) - result = response.get('status_code') + result = response.get("status_code") assert result == 202 - assert response.get('status_code') + assert response.get("status_code") def test_deploy_stack_yoda(): - response = request_url(verb='POST', uri=f'deploy/{uri}', headers={ - "Authorization": f"Bearer {token}"}, json=data_master) - if response.get('status_code') != 409: - task_id = response.get('json').get('task').get('task_id') - while get_task_id(task_id).get('json').get( - 'result').get('state') != 'SUCCESS': + response = request_url( + verb="POST", + uri=f"deploy/{uri}", + headers={"Authorization": f"Bearer {token}"}, + json=data_master, + ) + if response.get("status_code") != 409: + task_id = response.get("json").get("task").get("task_id") + while get_task_id(task_id).get("json").get("result").get("state") != "SUCCESS": time.sleep(3) - result = response.get('status_code') + result = response.get("status_code") assert result == 202 - assert response.get('status_code') + assert response.get("status_code") def test_get_deploy_by_id(): - response = request_url(verb='GET', uri='deploy/?limit=1', headers={ - "Authorization": f"Bearer {token}"}) - deploy_id = response.get('json')[0].get("id") - response = request_url(verb='GET', - uri=f'deploy/{deploy_id}', - headers={"Authorization": f"Bearer {token}"}) - result = response.get('status_code') + response = request_url( + verb="GET", uri="deploy/?limit=1", headers={"Authorization": f"Bearer {token}"} + ) + deploy_id = response.get("json")[0].get("id") + response = request_url( + verb="GET", + uri=f"deploy/{deploy_id}", + headers={"Authorization": f"Bearer {token}"}, + ) + result = response.get("status_code") assert result == 200 def test_get_deploy_outputs(): - response = request_url(verb='GET', uri='deploy/?limit=1', headers={ - "Authorization": f"Bearer {token}"}) - deploy_id = response.get('json')[0].get("id") response = request_url( - verb='GET', - uri=f'deploy/output/{deploy_id}', - headers={ - "Authorization": f"Bearer {token}"}) - result = response.get('status_code') + verb="GET", uri="deploy/?limit=1", headers={"Authorization": f"Bearer {token}"} + ) + deploy_id = response.get("json")[0].get("id") + response = request_url( + verb="GET", + uri=f"deploy/output/{deploy_id}", + headers={"Authorization": f"Bearer {token}"}, + ) + result = response.get("status_code") assert result == 200 def test_get_all_tasks(): - response = request_url(verb='GET', uri='tasks/all?limit=100', headers={ - "Authorization": f"Bearer {token}"}) - result = response.get('status_code') + response = request_url( + verb="GET", + uri="tasks/all?limit=100", + headers={"Authorization": f"Bearer {token}"}, + ) + result = response.get("status_code") assert result == 200 def test_update_stack(): - response = request_url(verb='GET', uri='deploy/?limit=1', headers={ - "Authorization": f"Bearer {token}"}) - deploy_id = response.get('json')[0].get("id") response = request_url( - verb='PATCH', - uri=f'deploy/{deploy_id}', - headers={ - "Authorization": f"Bearer {token}"}, - json=data_update) - task_id = response.get('json').get('task').get('task_id') - while get_task_id(task_id).get('json').get( - 'result').get('state') != 'SUCCESS': + verb="GET", uri="deploy/?limit=1", headers={"Authorization": f"Bearer {token}"} + ) + deploy_id = response.get("json")[0].get("id") + response = request_url( + verb="PATCH", + uri=f"deploy/{deploy_id}", + headers={"Authorization": f"Bearer {token}"}, + json=data_update, + ) + task_id = response.get("json").get("task").get("task_id") + while get_task_id(task_id).get("json").get("result").get("state") != "SUCCESS": time.sleep(3) - result = response.get('status_code') + result = response.get("status_code") assert result == 202 def test_destroy_stack(): - response = request_url(verb='GET', uri='deploy/?limit=1', headers={ - "Authorization": f"Bearer {token}"}) - deploy_id = response.get('json')[0].get("id") - response = request_url(verb='DELETE', uri=f'deploy/{deploy_id}', headers={ - "Authorization": f"Bearer {token}"}) - task_id = response.get('json').get('task').get('task_id') - while get_task_id(task_id).get('json').get( - 'result').get('state') != 'SUCCESS': + response = request_url( + verb="GET", uri="deploy/?limit=1", headers={"Authorization": f"Bearer {token}"} + ) + deploy_id = response.get("json")[0].get("id") + response = request_url( + verb="DELETE", + uri=f"deploy/{deploy_id}", + headers={"Authorization": f"Bearer {token}"}, + ) + task_id = response.get("json").get("task").get("task_id") + while get_task_id(task_id).get("json").get("result").get("state") != "SUCCESS": time.sleep(3) - result = response.get('status_code') + result = response.get("status_code") assert result == 200 diff --git a/sld-dashboard/app/__init__.py b/sld-dashboard/app/__init__.py index 22891577..42a2b586 100644 --- a/sld-dashboard/app/__init__.py +++ b/sld-dashboard/app/__init__.py @@ -1,10 +1,11 @@ # -*- encoding: utf-8 -*- +from importlib import import_module +from logging import DEBUG, StreamHandler, basicConfig, getLogger +from os import path + from flask import Flask, url_for from flask_login import LoginManager from flask_sqlalchemy import SQLAlchemy -from importlib import import_module -from logging import basicConfig, DEBUG, getLogger, StreamHandler -from os import path db = SQLAlchemy() login_manager = LoginManager() @@ -16,13 +17,12 @@ def register_extensions(app): def register_blueprints(app): - for module_name in ('base', 'home'): - module = import_module('app.{}.routes'.format(module_name)) + for module_name in ("base", "home"): + module = import_module("app.{}.routes".format(module_name)) app.register_blueprint(module.blueprint) def configure_database(app): - @app.before_first_request def initialize_database(): try: @@ -36,7 +36,7 @@ def shutdown_session(exception=None): def create_app(config): - app = Flask(__name__, static_folder='base/static') + app = Flask(__name__, static_folder="base/static") app.config.from_object(config) register_extensions(app) register_blueprints(app) diff --git a/sld-dashboard/app/base/__init__.py b/sld-dashboard/app/base/__init__.py index 679c7532..ba7ea1a5 100644 --- a/sld-dashboard/app/base/__init__.py +++ b/sld-dashboard/app/base/__init__.py @@ -2,9 +2,9 @@ from flask import Blueprint blueprint = Blueprint( - 'base_blueprint', + "base_blueprint", __name__, - url_prefix='', - template_folder='templates', - static_folder='static' + url_prefix="", + template_folder="templates", + static_folder="static", ) diff --git a/sld-dashboard/app/base/forms.py b/sld-dashboard/app/base/forms.py index af5de957..db60634f 100644 --- a/sld-dashboard/app/base/forms.py +++ b/sld-dashboard/app/base/forms.py @@ -1,15 +1,21 @@ # -*- encoding: utf-8 -*- from flask_wtf import FlaskForm -from wtforms import StringField, PasswordField -from wtforms.validators import InputRequired, Email, DataRequired +from wtforms import PasswordField, StringField +from wtforms.validators import DataRequired, Email ## login and registration + class LoginForm(FlaskForm): - username = StringField ('Username', id='username_login' , validators=[DataRequired()]) - password = PasswordField('Password', id='pwd_login' , validators=[DataRequired()]) + username = StringField("Username", id="username_login", validators=[DataRequired()]) + password = PasswordField("Password", id="pwd_login", validators=[DataRequired()]) + class CreateAccountForm(FlaskForm): - username = StringField('Username' , id='username_create' , validators=[DataRequired()]) - email = StringField('Email' , id='email_create' , validators=[DataRequired(), Email()]) - password = PasswordField('Password' , id='pwd_create' , validators=[DataRequired()]) + username = StringField( + "Username", id="username_create", validators=[DataRequired()] + ) + email = StringField( + "Email", id="email_create", validators=[DataRequired(), Email()] + ) + password = PasswordField("Password", id="pwd_create", validators=[DataRequired()]) diff --git a/sld-dashboard/app/base/models.py b/sld-dashboard/app/base/models.py index 932725df..dbbcdd2c 100644 --- a/sld-dashboard/app/base/models.py +++ b/sld-dashboard/app/base/models.py @@ -1,16 +1,17 @@ # -*- encoding: utf-8 -*- -from app import db, login_manager import datetime -import bcrypt + +from app import db, login_manager from flask_login import UserMixin -from sqlalchemy import Column, Integer, String, JSON from passlib.context import CryptContext +from sqlalchemy import JSON + pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") class User(db.Model, UserMixin): - __tablename__ = 'users' + __tablename__ = "users" id = db.Column(db.Integer, primary_key=True, index=True) username = db.Column(db.String(50), unique=True, nullable=False) @@ -66,7 +67,7 @@ def user_loader(id): @login_manager.request_loader def request_loader(request): - username = request.form.get('username') + username = request.form.get("username") user = User.query.filter_by(username=username).first() return user if user else None @@ -82,7 +83,7 @@ class Stack(db.Model): var_list = db.Column(db.JSON) created_at = db.Column(db.DateTime, default=datetime.datetime.now()) description = db.Column(db.Text()) - user_id = db.Column(db.Integer, db.ForeignKey('users.id')) + user_id = db.Column(db.Integer, db.ForeignKey("users.id")) owner = db.relationship("User", back_populates="stacks") @property @@ -93,11 +94,7 @@ def little_description(self): @classmethod def create_element(cls, name, git, description, user_id): - stack = Stack( - name=name, - git=git, - description=description, - user_id=user_id) + stack = Stack(name=name, git=git, description=description, user_id=user_id) db.session.add(stack) db.session.commit() @@ -146,7 +143,7 @@ class Aws_provider(db.Model): secret_access_key = db.Column(db.String(200), nullable=False) default_region = db.Column(db.String(200)) created_at = db.Column(db.DateTime, default=datetime.datetime.now()) - __table_args__ = (db.UniqueConstraint('squad', 'environment'),) + __table_args__ = (db.UniqueConstraint("squad", "environment"),) class Gcloud_provider(db.Model): @@ -156,7 +153,7 @@ class Gcloud_provider(db.Model): squad = db.Column(db.String(200), nullable=False) gcloud_keyfile_json = db.Column(db.String(5000), nullable=False) created_at = db.Column(db.DateTime, default=datetime.datetime.now()) - __table_args__ = (db.UniqueConstraint('squad', 'environment'),) + __table_args__ = (db.UniqueConstraint("squad", "environment"),) class Azure_provider(db.Model): @@ -169,7 +166,7 @@ class Azure_provider(db.Model): subscription_id = db.Column(db.String(200), nullable=False) tenant_id = db.Column(db.String(200), nullable=False) created_at = db.Column(db.DateTime, default=datetime.datetime.now()) - __table_args__ = (db.UniqueConstraint('squad', 'environment'),) + __table_args__ = (db.UniqueConstraint("squad", "environment"),) class Deploy(db.Model): @@ -184,8 +181,9 @@ class Deploy(db.Model): squad = db.Column(db.String(50), nullable=False) variables = db.Column(db.JSON) environment = db.Column(db.String(50)) - __table_args__ = (db.UniqueConstraint( - 'squad', 'environment', 'name', 'stack_name'),) + __table_args__ = ( + db.UniqueConstraint("squad", "environment", "name", "stack_name"), + ) class Tasks(db.Model): diff --git a/sld-dashboard/app/base/routes.py b/sld-dashboard/app/base/routes.py index f04f1e15..12dd734a 100644 --- a/sld-dashboard/app/base/routes.py +++ b/sld-dashboard/app/base/routes.py @@ -1,27 +1,13 @@ # -*- encoding: utf-8 -*- -from flask import jsonify, render_template, redirect, request, url_for -from flask_login import ( - current_user, - login_required, - login_user, - logout_user -) -import requests -import json import redis -import ast - - from app import db, login_manager from app.base import blueprint -from app.base.forms import LoginForm, CreateAccountForm +from app.base.forms import CreateAccountForm, LoginForm from app.base.models import User - from app.helpers.api_token import get_token -from app.helpers.api_request import request_url -from app.helpers.converter import convert_to_dict -from app.helpers.config.api import settings from app.helpers.security import vault_encrypt +from flask import redirect, render_template, request, url_for +from flask_login import current_user, login_user, logout_user @vault_encrypt @@ -33,30 +19,27 @@ def encrypt(secreto): # Move to config -r = redis.Redis(host='redis', port=6379, db=1, - charset="utf-8", decode_responses=True) +r = redis.Redis(host="redis", port=6379, db=1, charset="utf-8", decode_responses=True) -@blueprint.route('/') +@blueprint.route("/") def route_default(): - return redirect(url_for('base_blueprint.login')) + return redirect(url_for("base_blueprint.login")) + ## Login & Registration -@blueprint.route('/login', methods=['GET', 'POST']) +@blueprint.route("/login", methods=["GET", "POST"]) def login(): login_form = LoginForm(request.form) - if 'login' in request.form: + if "login" in request.form: # read form data - username = request.form['username'] - password = request.form['password'] + username = request.form["username"] + password = request.form["password"] - data_credentials: dict = { - "username": username, - "password": password - } + data_credentials: dict = {"username": username, "password": password} # Locate user db.session.remove() @@ -66,94 +49,106 @@ def login(): # Check the password if user and user.verify_password(password): if not current_user.is_active: - return render_template('accounts/login.html', msg='Inactive user ¯\_(ツ)_/¯', form=login_form) + return render_template( + "accounts/login.html", + msg="Inactive user ¯\_(ツ)_/¯", + form=login_form, + ) # Get token user token = get_token(data_credentials) # Store session in redis by user id r.set(current_user.id, encrypt(token)) login_user(user) - return redirect(url_for('base_blueprint.route_default')) + return redirect(url_for("base_blueprint.route_default")) # Something (user or pass) is not ok - return render_template('accounts/login.html', msg='Wrong user or password', form=login_form) + return render_template( + "accounts/login.html", msg="Wrong user or password", form=login_form + ) if not current_user.is_authenticated: - return render_template('accounts/login.html', - form=login_form) - return redirect(url_for('home_blueprint.index')) + return render_template("accounts/login.html", form=login_form) + return redirect(url_for("home_blueprint.index")) -@blueprint.route('/register', methods=['GET', 'POST']) +@blueprint.route("/register", methods=["GET", "POST"]) def register(): - login_form = LoginForm(request.form) + LoginForm(request.form) create_account_form = CreateAccountForm(request.form) - if 'register' in request.form: + if "register" in request.form: - username = request.form['username'] - email = request.form['email'] + username = request.form["username"] + email = request.form["email"] # Check usename exists user = User.query.filter_by(username=username).first() if user: - return render_template('accounts/register.html', - msg='Username already registered', - success=False, - form=create_account_form) + return render_template( + "accounts/register.html", + msg="Username already registered", + success=False, + form=create_account_form, + ) # Check email exists user = User.query.filter_by(email=email).first() if user: - return render_template('accounts/register.html', - msg='Email already registered', - success=False, - form=create_account_form) + return render_template( + "accounts/register.html", + msg="Email already registered", + success=False, + form=create_account_form, + ) # else we can create the user user = User(**request.form) db.session.add(user) db.session.commit() - return render_template('accounts/register.html', - msg='User created please login', - success=True, - form=create_account_form) + return render_template( + "accounts/register.html", + msg='User created please login', + success=True, + form=create_account_form, + ) else: - return render_template('accounts/register.html', form=create_account_form) + return render_template("accounts/register.html", form=create_account_form) -@blueprint.route('/logout') +@blueprint.route("/logout") def logout(): logout_user() - return redirect(url_for('base_blueprint.login')) + return redirect(url_for("base_blueprint.login")) -@blueprint.route('/shutdown') +@blueprint.route("/shutdown") def shutdown(): - func = request.environ.get('werkzeug.server.shutdown') + func = request.environ.get("werkzeug.server.shutdown") if func is None: - raise RuntimeError('Not running with the Werkzeug Server') + raise RuntimeError("Not running with the Werkzeug Server") func() - return 'Server shutting down...' + return "Server shutting down..." + # Errors @login_manager.unauthorized_handler def unauthorized_handler(): - return render_template('page-403.html'), 403 + return render_template("page-403.html"), 403 @blueprint.errorhandler(403) def access_forbidden(error): - return render_template('page-403.html'), 403 + return render_template("page-403.html"), 403 @blueprint.errorhandler(404) def not_found_error(error): - return render_template('page-404.html'), 404 + return render_template("page-404.html"), 404 @blueprint.errorhandler(500) def internal_error(error): - return render_template('page-500.html'), 500 + return render_template("page-500.html"), 500 diff --git a/sld-dashboard/app/base/static/assets/vendor/pyscript/pyscript.py b/sld-dashboard/app/base/static/assets/vendor/pyscript/pyscript.py index b57e5022..ea7406cb 100644 --- a/sld-dashboard/app/base/static/assets/vendor/pyscript/pyscript.py +++ b/sld-dashboard/app/base/static/assets/vendor/pyscript/pyscript.py @@ -364,7 +364,6 @@ def pre_child_append(self, child): def child_appended(self, child): """Overwrite me to define logic""" - pass class OutputCtxManager: diff --git a/sld-dashboard/app/base/templates/includes/sidebar.html b/sld-dashboard/app/base/templates/includes/sidebar.html index 64433873..1b2247ef 100644 --- a/sld-dashboard/app/base/templates/includes/sidebar.html +++ b/sld-dashboard/app/base/templates/includes/sidebar.html @@ -72,7 +72,7 @@