Skip to content

Commit

Permalink
Merge pull request #212 from D10S0VSkY-OSS/feature/metadata_filters
Browse files Browse the repository at this point in the history
🔥feat: Add filter and metadata vars
  • Loading branch information
D10S0VSkY-OSS authored Dec 7, 2023
2 parents 4318e9d + 5527db0 commit 67bf4eb
Show file tree
Hide file tree
Showing 18 changed files with 601 additions and 66 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/sld-api-docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ jobs:
- name: Build the Docker image with tag
working-directory: ./sld-api-backend
run: docker build . --file Dockerfile --tag ${{ secrets.DOCKER_USERNAME }}/sld-api:3.0.0
run: docker build . --file Dockerfile --tag ${{ secrets.DOCKER_USERNAME }}/sld-api:3.1.0

- name: Docker Push with tag
#if: github.event.pull_request.merged == true
run: docker push ${{ secrets.DOCKER_USERNAME }}/sld-api:3.0.0
run: docker push ${{ secrets.DOCKER_USERNAME }}/sld-api:3.1.0

- name: Build the Docker image
working-directory: ./sld-api-backend
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/sld-dashboard-docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ jobs:
- name: Build the Docker image with tags
working-directory: ./sld-dashboard
run: docker build . --file Dockerfile --tag ${{ secrets.DOCKER_USERNAME }}/sld-dashboard:3.0.0
run: docker build . --file Dockerfile --tag ${{ secrets.DOCKER_USERNAME }}/sld-dashboard:3.1.0

- name: Docker Push with tags
#if: github.event.pull_request.merged == true
run: docker push ${{ secrets.DOCKER_USERNAME }}/sld-dashboard:3.0.0
run: docker push ${{ secrets.DOCKER_USERNAME }}/sld-dashboard:3.1.0
- name: Build the Docker image
working-directory: ./sld-dashboard
run: docker build . --file Dockerfile --tag ${{ secrets.DOCKER_USERNAME }}/sld-dashboard:latest
Expand Down
2 changes: 1 addition & 1 deletion play-with-sld/kubernetes/k8s/sld-api-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ spec:
subdomain: primary
containers:
- name: api-backend
image: d10s0vsky/sld-api:3.0.0
image: d10s0vsky/sld-api:3.1.0
imagePullPolicy: Always
command: ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1"]
ports:
Expand Down
2 changes: 1 addition & 1 deletion play-with-sld/kubernetes/k8s/sld-dashboard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ spec:
subdomain: primary
containers:
- name: sld-dashboard
image: d10s0vsky/sld-dashboard:3.0.0
image: d10s0vsky/sld-dashboard:3.1.0
env:
- name: PATH
value: "/home/sld/.asdf/shims:/home/sld/.asdf/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Expand Down
2 changes: 1 addition & 1 deletion play-with-sld/kubernetes/k8s/sld-worker-default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ spec:
subdomain: primary
containers:
- name: stack-deploy-worker-default
image: d10s0vsky/sld-api:3.0.0
image: d10s0vsky/sld-api:3.1.0
imagePullPolicy: Always
env:
- name: TF_WARN_OUTPUT_ERRORS
Expand Down
2 changes: 1 addition & 1 deletion play-with-sld/kubernetes/k8s/sld-worker-squad1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ spec:
subdomain: primary
containers:
- name: stack-deploy-worker-squad1
image: d10s0vsky/sld-api:3.0.0
image: d10s0vsky/sld-api:3.1.0
imagePullPolicy: Always
env:
- name: TF_WARN_OUTPUT_ERRORS
Expand Down
2 changes: 1 addition & 1 deletion play-with-sld/kubernetes/k8s/sld-worker-squad2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ spec:
subdomain: primary
containers:
- name: stack-deploy-worker-squad2
image: d10s0vsky/sld-api:3.0.0
image: d10s0vsky/sld-api:3.1.0
imagePullPolicy: Always
env:
- name: TF_WARN_OUTPUT_ERRORS
Expand Down
47 changes: 37 additions & 10 deletions sld-api-backend/src/deploy/api/container/deploy/get.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,28 @@
from src.shared.security import deps
from src.users.domain.entities import users as schemas_users
from src.users.infrastructure import repositories as crud_users
from typing import List
from src.deploy.domain.entities.repository import DeployFilter, DeployFilterResponse
from src.deploy.domain.entities.metrics import AllMetricsResponse
from src.deploy.infrastructure.repositories import MetricsFetcher
from config.api import settings





async def get_all_deploys(
current_user: schemas_users.User = Depends(deps.get_current_active_user),
skip: int = 0,
limit: int = 100,
db: Session = Depends(deps.get_db),
):
filters: DeployFilter = Depends(DeployFilter),
) -> List[DeployFilterResponse]:
try:
# Si el usuario no es un maestro, aplicar el filtro de escuadrón
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(db=db, skip=skip, limit=limit)
filters.squad = current_user.squad

return crud_deploys.get_deploys(db=db, filters=filters, skip=skip, limit=limit)
except Exception as err:
raise HTTPException(status_code=400, detail=f"{err}")
raise HTTPException(status_code=400, detail=str(err))


async def get_deploy_by_id(
Expand Down Expand Up @@ -142,3 +143,29 @@ async def lock_deploy(
return response.json()
except Exception as err:
raise err


async def get_all_metrics(
db: Session = Depends(deps.get_db),
_current_user: schemas_users.User = Depends(deps.get_current_active_user),
) -> AllMetricsResponse:
metrics_fetcher = MetricsFetcher(db)
user_activity = metrics_fetcher.get_deploy_count_by_user()
action_count = metrics_fetcher.get_deploy_count_by_action()
environment_count = metrics_fetcher.get_deploy_count_by_environment()
stack_usage = metrics_fetcher.get_deploy_count_by_stack_name()
monthly_deploy_count = metrics_fetcher.get_monthly_deploy_count()
squad_deploy_count = metrics_fetcher.get_deploy_count_by_squad()
cloud_provider_usage = metrics_fetcher.get_cloud_provider_usage()
squad_environment_usage = metrics_fetcher.get_squad_environment_usage()

return AllMetricsResponse(
user_activity=user_activity,
action_count=action_count,
environment_count=environment_count,
stack_usage=stack_usage,
monthly_deploy_count=monthly_deploy_count,
squad_deploy_count=squad_deploy_count,
cloud_provider_usage=cloud_provider_usage,
squad_environment_usage=squad_environment_usage,
)
13 changes: 11 additions & 2 deletions sld-api-backend/src/deploy/api/v1/deploy.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from fastapi import APIRouter, Depends
from typing import List

from src.deploy.api.container.deploy import create, delete, destroy, get, update
from src.deploy.domain.entities import deploy as schemas_deploy
from src.deploy.domain.entities.repository import DeployFilterResponse, DeployFilter

router = APIRouter()

Expand Down Expand Up @@ -36,9 +38,9 @@ async def delete_infra_by_id(
return delete_deploy


@router.get("/")
@router.get("/", status_code=200, response_model=List[DeployFilterResponse])
async def get_all_deploys(
get_all_deploys: schemas_deploy.DeployBase = Depends(get.get_all_deploys),
get_all_deploys: DeployFilterResponse = Depends(get.get_all_deploys),
):
return get_all_deploys

Expand Down Expand Up @@ -75,3 +77,10 @@ async def get_show(
get_show: schemas_deploy.DeployBase = Depends(get.get_show),
):
return get_show


@router.get("/metrics/all")
async def get_metrics(
get_metrics: schemas_deploy.DeployBase = Depends(get.get_all_metrics),
):
return get_metrics
4 changes: 2 additions & 2 deletions sld-api-backend/src/deploy/domain/entities/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ class DeployDeleteMaster(BaseModel):


class DeployUpdate(BaseModel):
start_time: constr(strip_whitespace=True)
destroy_time: constr(strip_whitespace=True)
start_time: Optional[constr(strip_whitespace=True)] = Field("")
destroy_time: Optional[constr(strip_whitespace=True)] = Field("")
stack_branch: Optional[constr(strip_whitespace=True)] = Field("", example="")
tfvar_file: Optional[constr(strip_whitespace=True)] = Field(
"", example="terraform.tfvars"
Expand Down
54 changes: 54 additions & 0 deletions sld-api-backend/src/deploy/domain/entities/metrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from pydantic import BaseModel
from typing import List


class UserActivity(BaseModel):
username: str
deploy_count: int


class ActionCount(BaseModel):
action: str
count: int


class EnvironmentCount(BaseModel):
environment: str
count: int


class StackUsage(BaseModel):
stack_name: str
count: int


class MonthlyDeployCount(BaseModel):
month: int
count: int


class SquadDeployCount(BaseModel):
squad: str
count: int


class CloudProviderUsage(BaseModel):
provider: str
count: int


class SquadEnvironmentUsage(BaseModel):
squad: str
environment: str
count: int


class AllMetricsResponse(BaseModel):
user_activity: List[UserActivity]
action_count: List[ActionCount]
environment_count: List[EnvironmentCount]
stack_usage: List[StackUsage]
monthly_deploy_count: List[MonthlyDeployCount]
squad_deploy_count: List[SquadDeployCount]
cloud_provider_usage: List[CloudProviderUsage]
squad_environment_usage: List[SquadEnvironmentUsage]
40 changes: 40 additions & 0 deletions sld-api-backend/src/deploy/domain/entities/repository.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from pydantic import BaseModel
from typing import Optional
from datetime import datetime


class DeployFilter(BaseModel):
id: Optional[str] = None
task_id: Optional[str] = None
name: Optional[str] = None
action: Optional[str] = None
stack_name: Optional[str] = None
stack_branch: Optional[str] = None
user_id: Optional[int] = None
username: Optional[str] = None
squad: Optional[str] = None
environment: Optional[str] = None
tfvar_file: Optional[str] = None
project_path: Optional[str] = None


class DeployFilterResponse(BaseModel):
id: int
task_id: str
name: str
action: str
start_time: Optional[str]
destroy_time: Optional[str]
stack_name: str
stack_branch: str
created_at: datetime
updated_at: Optional[datetime]
user_id: int
username: str
squad: str
variables: dict
environment: str
tfvar_file: Optional[str]
project_path: Optional[str]


94 changes: 92 additions & 2 deletions sld-api-backend/src/deploy/infrastructure/repositories.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import datetime

from typing import List
from sqlalchemy.orm import Session
from sqlalchemy import desc
from sqlalchemy import func, extract, desc, case

import src.deploy.domain.entities.deploy as schemas_deploy
from src.deploy.domain.entities.repository import DeployFilter, DeployFilterResponse
from src.deploy.domain.entities.metrics import ActionCount, EnvironmentCount, MonthlyDeployCount, SquadDeployCount, StackUsage, UserActivity, CloudProviderUsage, SquadEnvironmentUsage
import src.deploy.infrastructure.models as models


Expand Down Expand Up @@ -204,3 +206,91 @@ def get_deploy_by_cloud_account(db: Session, squad: str, environment: str):
)
except Exception as err:
raise err

def get_deploys(db: Session, filters: DeployFilter, skip: int = 0, limit: int = 100) -> List[DeployFilterResponse]:
query = db.query(models.Deploy)

for field, value in filters.model_dump().items():
if value is not None:
if field == 'squad' and isinstance(value, list):
query = query.filter(getattr(models.Deploy, field).in_(value))
else:
query = query.filter(getattr(models.Deploy, field) == value)

deploys = query.order_by(desc(models.Deploy.id)).offset(skip).limit(limit).all()
return [DeployFilterResponse(**deploy.__dict__) for deploy in deploys]


class MetricsFetcher:
def __init__(self, db: Session):
self.db = db

def get_deploy_count_by_user(self) -> List[UserActivity]:
query_result = self.db.query(
models.Deploy.username,
func.count(models.Deploy.id)
).group_by(models.Deploy.username).all()
return [UserActivity(username=username, deploy_count=count) for username, count in query_result]

def get_deploy_count_by_action(self) -> List[ActionCount]:
query_result = self.db.query(
models.Deploy.action,
func.count(models.Deploy.id)
).group_by(models.Deploy.action).all()
return [ActionCount(action=action, count=count) for action, count in query_result]

def get_deploy_count_by_environment(self) -> List[EnvironmentCount]:
query_result = self.db.query(
models.Deploy.environment,
func.count(models.Deploy.id)
).group_by(models.Deploy.environment).all()
return [EnvironmentCount(environment=environment, count=count) for environment, count in query_result]

def get_deploy_count_by_stack_name(self) -> List[StackUsage]:
query_result = self.db.query(
models.Deploy.stack_name,
func.count(models.Deploy.id)
).group_by(models.Deploy.stack_name).all()
return [StackUsage(stack_name=stack_name, count=count) for stack_name, count in query_result]

def get_monthly_deploy_count(self) -> List[MonthlyDeployCount]:
query_result = self.db.query(
extract('month', models.Deploy.created_at),
func.count(models.Deploy.id)
).group_by(extract('month', models.Deploy.created_at)).all()
return [MonthlyDeployCount(month=month, count=count) for month, count in query_result]

def get_deploy_count_by_squad(self) -> List[SquadDeployCount]:
query_result = self.db.query(
models.Deploy.squad,
func.count(models.Deploy.id)
).group_by(models.Deploy.squad).all()
return [SquadDeployCount(squad=squad, count=count) for squad, count in query_result]

def get_cloud_provider_usage(self) -> List[CloudProviderUsage]:
stacks = self.db.query(models.Deploy.stack_name).all()
counts = {'aws': 0, 'azure': 0, 'gcp': 0, 'custom': 0}

for (stack_name,) in stacks:
for provider in counts.keys():
if stack_name.startswith(provider + '_'):
counts[provider] += 1
break

return [CloudProviderUsage(provider=provider, count=count)
for provider, count in counts.items() if count > 0]

def get_squad_environment_usage(self) -> List[SquadEnvironmentUsage]:
results = self.db.query(
models.Deploy.squad,
models.Deploy.environment,
func.count(models.Deploy.id)
).group_by(
models.Deploy.squad,
models.Deploy.environment
).all()

return [
SquadEnvironmentUsage(squad=squad, environment=environment, count=count)
for squad, environment, count in results
]
Loading

0 comments on commit 67bf4eb

Please sign in to comment.