Add system namespace filtering
- Add configuration to exclude system namespaces by default - Add UI checkbox to include system namespaces when needed - Update API endpoints to accept include_system_namespaces parameter - Update Kubernetes client to apply namespace filtering - Update ConfigMap and deployment with new environment variables - Fix Dockerfile to install dependencies globally - Test functionality with both filtered and unfiltered results
This commit is contained in:
@@ -29,11 +29,9 @@ RUN groupadd -r appuser && useradd -r -g appuser appuser
|
|||||||
RUN mkdir -p /app /tmp/reports && \
|
RUN mkdir -p /app /tmp/reports && \
|
||||||
chown -R appuser:appuser /app /tmp/reports
|
chown -R appuser:appuser /app /tmp/reports
|
||||||
|
|
||||||
# Copiar dependências Python do stage anterior
|
# Instalar dependências Python globalmente
|
||||||
COPY --from=builder /root/.local /home/appuser/.local
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
# Definir PATH para incluir dependências locais
|
|
||||||
ENV PATH=/home/appuser/.local/bin:$PATH
|
|
||||||
|
|
||||||
# Definir diretório de trabalho
|
# Definir diretório de trabalho
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
@@ -175,12 +175,13 @@ async def get_validations_by_namespace(
|
|||||||
severity: Optional[str] = None,
|
severity: Optional[str] = None,
|
||||||
page: int = 1,
|
page: int = 1,
|
||||||
page_size: int = 20,
|
page_size: int = 20,
|
||||||
|
include_system_namespaces: bool = False,
|
||||||
k8s_client=Depends(get_k8s_client)
|
k8s_client=Depends(get_k8s_client)
|
||||||
):
|
):
|
||||||
"""Listar validações agrupadas por namespace com paginação"""
|
"""Listar validações agrupadas por namespace com paginação"""
|
||||||
try:
|
try:
|
||||||
# Coletar todos os pods
|
# Coletar todos os pods com filtro de namespaces do sistema
|
||||||
pods = await k8s_client.get_all_pods()
|
pods = await k8s_client.get_all_pods(include_system_namespaces=include_system_namespaces)
|
||||||
|
|
||||||
# Validar recursos e agrupar por namespace
|
# Validar recursos e agrupar por namespace
|
||||||
namespace_validations = {}
|
namespace_validations = {}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ Configurações da aplicação
|
|||||||
import os
|
import os
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
from pydantic_settings import BaseSettings
|
from pydantic_settings import BaseSettings
|
||||||
|
from pydantic import Field
|
||||||
|
|
||||||
class Settings(BaseSettings):
|
class Settings(BaseSettings):
|
||||||
"""Configurações da aplicação"""
|
"""Configurações da aplicação"""
|
||||||
@@ -31,6 +32,24 @@ class Settings(BaseSettings):
|
|||||||
"openshift-sdn"
|
"openshift-sdn"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Configurações de filtro de namespaces
|
||||||
|
include_system_namespaces: bool = Field(default=False, alias="INCLUDE_SYSTEM_NAMESPACES")
|
||||||
|
system_namespace_prefixes: List[str] = Field(
|
||||||
|
default=[
|
||||||
|
"kube-",
|
||||||
|
"openshift-",
|
||||||
|
"default",
|
||||||
|
"kube-system",
|
||||||
|
"kube-public",
|
||||||
|
"kube-node-lease"
|
||||||
|
],
|
||||||
|
alias="SYSTEM_NAMESPACE_PREFIXES"
|
||||||
|
)
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
env_file = ".env"
|
||||||
|
case_sensitive = False
|
||||||
|
|
||||||
# Configurações de relatório
|
# Configurações de relatório
|
||||||
report_export_path: str = "/tmp/reports"
|
report_export_path: str = "/tmp/reports"
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,20 @@ class K8sClient:
|
|||||||
logger.error(f"Erro ao inicializar cliente Kubernetes: {e}")
|
logger.error(f"Erro ao inicializar cliente Kubernetes: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
async def get_all_pods(self) -> List[PodResource]:
|
def _is_system_namespace(self, namespace: str, include_system: bool = None) -> bool:
|
||||||
|
"""Verificar se um namespace é do sistema"""
|
||||||
|
# Usar parâmetro se fornecido, senão usar configuração global
|
||||||
|
should_include = include_system if include_system is not None else settings.include_system_namespaces
|
||||||
|
|
||||||
|
if should_include:
|
||||||
|
return False
|
||||||
|
|
||||||
|
for prefix in settings.system_namespace_prefixes:
|
||||||
|
if namespace.startswith(prefix):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def get_all_pods(self, include_system_namespaces: bool = None) -> List[PodResource]:
|
||||||
"""Coletar informações de todos os pods do cluster"""
|
"""Coletar informações de todos os pods do cluster"""
|
||||||
if not self.initialized:
|
if not self.initialized:
|
||||||
raise RuntimeError("Cliente Kubernetes não inicializado")
|
raise RuntimeError("Cliente Kubernetes não inicializado")
|
||||||
@@ -56,6 +69,9 @@ class K8sClient:
|
|||||||
pods = self.v1.list_pod_for_all_namespaces(watch=False)
|
pods = self.v1.list_pod_for_all_namespaces(watch=False)
|
||||||
|
|
||||||
for pod in pods.items:
|
for pod in pods.items:
|
||||||
|
# Filtrar namespaces do sistema
|
||||||
|
if self._is_system_namespace(pod.metadata.namespace, include_system_namespaces):
|
||||||
|
continue
|
||||||
pod_resource = PodResource(
|
pod_resource = PodResource(
|
||||||
name=pod.metadata.name,
|
name=pod.metadata.name,
|
||||||
namespace=pod.metadata.namespace,
|
namespace=pod.metadata.namespace,
|
||||||
@@ -102,6 +118,18 @@ class K8sClient:
|
|||||||
if not self.initialized:
|
if not self.initialized:
|
||||||
raise RuntimeError("Cliente Kubernetes não inicializado")
|
raise RuntimeError("Cliente Kubernetes não inicializado")
|
||||||
|
|
||||||
|
# Verificar se é namespace do sistema
|
||||||
|
if self._is_system_namespace(namespace):
|
||||||
|
logger.info(f"Namespace {namespace} é do sistema, retornando vazio")
|
||||||
|
return NamespaceResources(
|
||||||
|
name=namespace,
|
||||||
|
pods=[],
|
||||||
|
total_cpu_requests="0",
|
||||||
|
total_cpu_limits="0",
|
||||||
|
total_memory_requests="0",
|
||||||
|
total_memory_limits="0"
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Listar pods do namespace
|
# Listar pods do namespace
|
||||||
pods = self.v1.list_namespaced_pod(namespace=namespace)
|
pods = self.v1.list_namespaced_pod(namespace=namespace)
|
||||||
|
|||||||
@@ -488,6 +488,19 @@
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.checkbox-label {
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: row !important;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-label input[type="checkbox"] {
|
||||||
|
margin: 0;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.container {
|
.container {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
@@ -635,6 +648,12 @@
|
|||||||
<option value="100">100</option>
|
<option value="100">100</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="filter-group">
|
||||||
|
<label class="checkbox-label">
|
||||||
|
<input type="checkbox" id="includeSystemNamespaces" onchange="loadValidationsByNamespace()">
|
||||||
|
Incluir namespaces do sistema
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<button class="btn" onclick="loadValidationsByNamespace()">Aplicar Filtros</button>
|
<button class="btn" onclick="loadValidationsByNamespace()">Aplicar Filtros</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -727,6 +746,7 @@
|
|||||||
try {
|
try {
|
||||||
const severity = document.getElementById('severityFilter').value;
|
const severity = document.getElementById('severityFilter').value;
|
||||||
const pageSize = parseInt(document.getElementById('pageSizeFilter').value);
|
const pageSize = parseInt(document.getElementById('pageSizeFilter').value);
|
||||||
|
const includeSystem = document.getElementById('includeSystemNamespaces').checked;
|
||||||
|
|
||||||
currentSeverity = severity;
|
currentSeverity = severity;
|
||||||
currentPageSize = pageSize;
|
currentPageSize = pageSize;
|
||||||
@@ -734,7 +754,8 @@
|
|||||||
|
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
page: currentPage,
|
page: currentPage,
|
||||||
page_size: currentPageSize
|
page_size: currentPageSize,
|
||||||
|
include_system_namespaces: includeSystem
|
||||||
});
|
});
|
||||||
|
|
||||||
if (severity) {
|
if (severity) {
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ data:
|
|||||||
# Namespaces críticos para VPA
|
# Namespaces críticos para VPA
|
||||||
CRITICAL_NAMESPACES: '["openshift-monitoring", "openshift-ingress", "openshift-apiserver", "openshift-controller-manager", "openshift-sdn"]'
|
CRITICAL_NAMESPACES: '["openshift-monitoring", "openshift-ingress", "openshift-apiserver", "openshift-controller-manager", "openshift-sdn"]'
|
||||||
|
|
||||||
|
# Configurações de filtro de namespaces
|
||||||
|
INCLUDE_SYSTEM_NAMESPACES: "false"
|
||||||
|
SYSTEM_NAMESPACE_PREFIXES: '["kube-", "openshift-", "default", "kube-system", "kube-public", "kube-node-lease"]'
|
||||||
|
|
||||||
# URL do Prometheus
|
# URL do Prometheus
|
||||||
PROMETHEUS_URL: "http://prometheus.openshift-monitoring.svc.cluster.local:9090"
|
PROMETHEUS_URL: "http://prometheus.openshift-monitoring.svc.cluster.local:9090"
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,16 @@ spec:
|
|||||||
configMapKeyRef:
|
configMapKeyRef:
|
||||||
name: resource-governance-config
|
name: resource-governance-config
|
||||||
key: CRITICAL_NAMESPACES
|
key: CRITICAL_NAMESPACES
|
||||||
|
- name: INCLUDE_SYSTEM_NAMESPACES
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: resource-governance-config
|
||||||
|
key: INCLUDE_SYSTEM_NAMESPACES
|
||||||
|
- name: SYSTEM_NAMESPACE_PREFIXES
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: resource-governance-config
|
||||||
|
key: SYSTEM_NAMESPACE_PREFIXES
|
||||||
- name: PROMETHEUS_URL
|
- name: PROMETHEUS_URL
|
||||||
valueFrom:
|
valueFrom:
|
||||||
configMapKeyRef:
|
configMapKeyRef:
|
||||||
|
|||||||
Reference in New Issue
Block a user