Skip to content

Commit

Permalink
[resotocore][feat] Maintain checks and benchmarks and allow custom ch…
Browse files Browse the repository at this point in the history
…ecks and benchmarks (#1873)
  • Loading branch information
aquamatthias authored Jan 12, 2024
1 parent 2a6aa16 commit 1e6110f
Show file tree
Hide file tree
Showing 17 changed files with 657 additions and 408 deletions.
6 changes: 3 additions & 3 deletions resotocore/resotocore/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
from resotocore.model.model_handler import ModelHandlerDB, ModelHandlerFromCodeAndDB
from resotocore.model.typed_model import to_json, class_fqn
from resotocore.query.template_expander_service import TemplateExpanderService
from resotocore.report.inspector_service import InspectorConfigService, InspectorFileService
from resotocore.report.inspector_service import InspectorService
from resotocore.system_start import db_access, setup_process, parse_args, system_info, reconfigure_logging
from resotocore.task.scheduler import APScheduler, NoScheduler
from resotocore.task.subscribers import SubscriptionHandlerService
Expand Down Expand Up @@ -198,7 +198,7 @@ async def direct_tenant(deps: TenantDependencies) -> None:
default_env = {"graph": config.cli.default_graph, "section": config.cli.default_section}
cli = deps.add(ServiceNames.cli, CLIService(deps, all_commands(deps), default_env, alias_names()))
deps.add(ServiceNames.template_expander, TemplateExpanderService(db.template_entity_db, cli))
inspector = deps.add(ServiceNames.inspector, InspectorConfigService(cli))
inspector = deps.add(ServiceNames.inspector, InspectorService(cli))
subscriptions = deps.add(ServiceNames.subscription_handler, SubscriptionHandlerService(message_bus))
core_config_handler = deps.add(
ServiceNames.core_config_handler,
Expand Down Expand Up @@ -250,7 +250,7 @@ async def direct_tenant(deps: TenantDependencies) -> None:
async def multi_tenancy(deps: Dependencies) -> None:
deps.add(ServiceNames.message_bus, MessageBus())
deps.add(ServiceNames.forked_tasks, Queue())
InspectorFileService.on_startup()
InspectorService.on_startup()
ModelHandlerFromCodeAndDB.on_startup()


Expand Down
30 changes: 17 additions & 13 deletions resotocore/resotocore/cli/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,6 @@
from detect_secrets.settings import configure_settings_from_baseline, default_settings
from parsy import Parser, string, ParseError
from resotoclient.models import Model as RCModel, Kind as RCKind
from resotodatalink import EngineConfig
from resotodatalink.batch_stream import BatchStream
from resotodatalink.collect_plugins import update_sql
from rich.padding import Padding
from rich.panel import Panel
from rich.table import Table
from rich.text import Text

from resotocore import version
from resotocore.async_extensions import run_async
from resotocore.cli import (
Expand Down Expand Up @@ -103,14 +95,12 @@
FilePath,
CLISourceContext,
)
from resotocore.user.model import Permission, AllowedRoleNames
from resotocore.cli.tip_of_the_day import SuggestionPolicy, SuggestionStrategy, get_suggestion_strategy
from resotocore.config import ConfigEntity
from resotocore.db.async_arangodb import AsyncCursor
from resotocore.db.graphdb import HistoryChange, GraphDB
from resotocore.db.model import QueryModel
from resotocore.db.runningtaskdb import RunningTaskData
from resotocore.system_start import system_info
from resotocore.error import CLIParseError, ClientError, CLIExecutionError, NotEnoughPermissions
from resotocore.ids import ConfigId, TaskId, InfraAppName, TaskDescriptorId, GraphName, Email, Password
from resotocore.infra_apps.manifest import AppManifest
Expand Down Expand Up @@ -148,11 +138,14 @@
)
from resotocore.query.query_parser import parse_query, aggregate_parameter_parser, predicate_term
from resotocore.query.template_expander import tpl_props_p
from resotocore.report import BenchmarkConfigPrefix, ReportSeverity
from resotocore.report import ReportSeverity
from resotocore.report.benchmark_renderer import respond_benchmark_result
from resotocore.report.report_config import BenchmarkConfig
from resotocore.system_start import system_info
from resotocore.task.task_description import Job, TimeTrigger, EventTrigger, ExecuteCommand, Workflow, RunningTask
from resotocore.types import Json, JsonElement, EdgeType
from resotocore.user import ResotoUser
from resotocore.user.model import Permission, AllowedRoleNames
from resotocore.util import (
uuid_str,
utc,
Expand All @@ -175,6 +168,9 @@
respond_cytoscape,
)
from resotocore.worker_task_queue import WorkerTask, WorkerTaskName
from resotodatalink import EngineConfig
from resotodatalink.batch_stream import BatchStream
from resotodatalink.collect_plugins import update_sql
from resotolib.core import CLIEnvelope
from resotolib.durations import parse_duration
from resotolib.parse_util import (
Expand All @@ -190,6 +186,10 @@
)
from resotolib.utils import safe_members_in_tarfile, get_local_tzinfo
from resotolib.x509 import write_cert_to_file, write_key_to_file
from rich.padding import Padding
from rich.panel import Panel
from rich.table import Table
from rich.text import Text

if TYPE_CHECKING:
from resotocore.dependencies import TenantDependencies
Expand Down Expand Up @@ -5026,8 +5026,12 @@ async def list_benchmarks() -> AsyncIterator[str]:
for benchmark in await self.dependencies.inspector.list_benchmarks():
yield benchmark.id

async def show_benchmark(bid: str) -> AsyncIterator[Optional[str]]:
yield await self.dependencies.config_handler.config_yaml(ConfigId(BenchmarkConfigPrefix + bid))
async def show_benchmark(bid: str) -> AsyncIterator[str]:
if benchmark := await self.dependencies.inspector.benchmark(bid):
model = await self.dependencies.config_handler.get_configs_model()
kind = model.get(BenchmarkConfig.kind)
js = to_json(benchmark)
yield kind.create_yaml(js) if isinstance(kind, ComplexKind) else yaml.safe_dump(js)

async def show_check(cid: str) -> AsyncIterator[str]:
model = await self.dependencies.config_handler.get_configs_model()
Expand Down
7 changes: 7 additions & 0 deletions resotocore/resotocore/db/db_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from resotocore.db.jobdb import job_db
from resotocore.db.modeldb import ModelDb, model_db
from resotocore.db.packagedb import app_package_entity_db
from resotocore.db.reportdb import report_check_db, benchmark_db
from resotocore.db.runningtaskdb import running_task_db
from resotocore.db.system_data_db import SystemDataDb
from resotocore.db.templatedb import template_entity_db
Expand Down Expand Up @@ -55,6 +56,8 @@ def __init__(
template_entity: str = "templates",
infra_app_packages: str = "infra_app_packages",
time_series: str = "ts",
report_checks: str = "report_checks",
benchmarks: str = "report_benchmarks",
):
super().__init__()
self.event_sender = event_sender
Expand All @@ -71,6 +74,8 @@ def __init__(
self.configs_model_db = model_db(self.db, configs_model)
self.template_entity_db = template_entity_db(self.db, template_entity)
self.package_entity_db = app_package_entity_db(self.db, infra_app_packages)
self.report_check_db = report_check_db(self.db, report_checks)
self.benchmark_db = benchmark_db(self.db, benchmarks)
self.time_series_db = TimeSeriesDB(self.db, time_series, config)
self.graph_dbs: Dict[str, GraphDB] = {}
self.config = config
Expand All @@ -87,6 +92,8 @@ async def start(self) -> None:
await self.deferred_outer_edge_db.create_update_schema()
await self.package_entity_db.create_update_schema()
await self.time_series_db.create_update_schema()
await self.report_check_db.create_update_schema()
await self.benchmark_db.create_update_schema()
for graph in cast(List[Json], self.database.graphs()):
graph_name = GraphName(graph["name"])

Expand Down
17 changes: 17 additions & 0 deletions resotocore/resotocore/db/reportdb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from resotocore.db.async_arangodb import AsyncArangoDB
from resotocore.db.entitydb import EntityDb, ArangoEntityDb, EventEntityDb
from resotocore.report import ReportCheck, Benchmark

ReportCheckDb = EntityDb[str, ReportCheck]
EventReportCheckDb = EventEntityDb[str, ReportCheck]

BenchmarkDb = EntityDb[str, Benchmark]
EventBenchmarkDb = EventEntityDb[str, Benchmark]


def report_check_db(db: AsyncArangoDB, collection: str) -> ArangoEntityDb[str, ReportCheck]:
return ArangoEntityDb(db, collection, ReportCheck, lambda k: k.id)


def benchmark_db(db: AsyncArangoDB, collection: str) -> ArangoEntityDb[str, Benchmark]:
return ArangoEntityDb(db, collection, Benchmark, lambda k: k.id)
4 changes: 2 additions & 2 deletions resotocore/resotocore/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
from resotocore.query.template_expander import TemplateExpander
from resotocore.query.template_expander_service import TemplateExpanderService
from resotocore.report import Inspector
from resotocore.report.inspector_service import InspectorFileService
from resotocore.report.inspector_service import InspectorService
from resotocore.service import Service
from resotocore.system_start import SystemInfo
from resotocore.task.scheduler import NoScheduler
Expand Down Expand Up @@ -419,7 +419,7 @@ def standard_database() -> StandardDatabase:
default_env = {"graph": config.cli.default_graph, "section": config.cli.default_section}
cli = deps.add(ServiceNames.cli, CLIService(deps, all_commands(deps), default_env, alias_names()))
deps.add(ServiceNames.template_expander, TemplateExpanderService(db.template_entity_db, cli))
inspector = deps.add(ServiceNames.inspector, InspectorFileService(cli))
inspector = deps.add(ServiceNames.inspector, InspectorService(cli))
subscriptions = deps.add(ServiceNames.subscription_handler, NoSubscriptionHandler())
core_config_handler = deps.add(
ServiceNames.core_config_handler,
Expand Down
30 changes: 23 additions & 7 deletions resotocore/resotocore/report/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from typing import List, Optional, Dict, ClassVar, AsyncIterator, cast, Set, Tuple, Union

from attr import define, field, evolve

from resotocore.ids import ConfigId, GraphName
from resotocore.model.typed_model import to_js
from resotocore.types import Json
Expand All @@ -16,15 +15,14 @@
log = logging.getLogger(__name__)

# config ids
ResotoReportValues = ConfigId("resoto.report.values")
ResotoReportConfig = ConfigId("resoto.report.config")
ResotoReportBenchmark = ConfigId("resoto.report.benchmark")
ResotoReportCheck = ConfigId("resoto.report.check")

# config keys and prefixes
CheckConfigPrefix = "resoto.report.check."
CheckConfigRoot = "report_check"
BenchmarkConfigPrefix = "resoto.report.benchmark."
BenchmarkConfigRoot = "report_benchmark"
ReportConfigRoot = "report_config"


class ReportSeverity(Enum):
Expand Down Expand Up @@ -75,8 +73,8 @@ class ReportCheck:
url: Optional[str] = None
related: Optional[List[str]] = None

def environment(self, values: Json) -> Json:
return {**self.default_values, **values} if self.default_values else values
def environment(self, override_values: Optional[Json] = None) -> Json:
return {**(self.default_values or {}), **(override_values or {})}

def to_node(self) -> Json:
reported = to_js(self)
Expand Down Expand Up @@ -333,7 +331,7 @@ async def list_benchmarks(self) -> List[Benchmark]:
pass

@abstractmethod
async def benchmark(self, name: str) -> Optional[Benchmark]:
async def benchmark(self, bid: str) -> Optional[Benchmark]:
pass

@abstractmethod
Expand All @@ -345,6 +343,7 @@ async def list_checks(
category: Optional[str] = None,
kind: Optional[str] = None,
check_ids: Optional[List[str]] = None,
ignore_checks: Optional[List[str]] = None,
) -> List[ReportCheck]:
"""
List all inspection checks matching the given criteria.
Expand All @@ -355,6 +354,7 @@ async def list_checks(
:param category: the category of the check (e.g. security, compliance, cost ...)
:param kind: the resulting kind of the check (e.g. aws_ec2_instance, kubernetes_pod, ...)
:param check_ids: the list of check ids to return
:param ignore_checks: ignore checks listed here
:return: the list of matching checks
"""

Expand Down Expand Up @@ -437,3 +437,19 @@ async def validate_benchmark_config(self, cfg_id: ConfigId, json: Json) -> Optio
@abstractmethod
async def validate_check_collection_config(self, json: Json) -> Optional[Json]:
pass

@abstractmethod
async def delete_benchmark(self, bid: str) -> None:
pass

@abstractmethod
async def update_benchmark(self, benchmark: Benchmark) -> Benchmark:
pass

@abstractmethod
async def delete_check(self, check_id: str) -> None:
pass

@abstractmethod
async def update_check(self, check: ReportCheck) -> ReportCheck:
pass
Loading

0 comments on commit 1e6110f

Please sign in to comment.