Skip to content

Commit

Permalink
Custom Capabilities in Candore
Browse files Browse the repository at this point in the history
  • Loading branch information
jyejare committed Jun 18, 2024
1 parent e8a2f56 commit bd93fcd
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 1 deletion.
3 changes: 3 additions & 0 deletions candore/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from candore.modules.extractor import Extractor
from candore.modules.finder import Finder
from candore.modules.report import Reporting
from candore.config import candore_settings


class Candore:
Expand All @@ -37,6 +38,8 @@ async def save_all_entities(self, mode, output_file, full):
if full:
extractor.full = True
data = await extractor.extract_all_entities()
if hasattr(self.settings, 'rpms'):
data.update({'installed_rpms': await extractor.extract_all_rpms()})

if not data:
click.echo("Entities data is not data found!")
Expand Down
1 change: 1 addition & 0 deletions candore/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def candore_settings(option_settings_file=None, option_components_file=None):
core_loaders=["YAML"],
envvar_prefix="CANDORE",
settings_files=[settings_file, components_file],
preload=["conf/*.yaml"],
envless_mode=True,
lowercase_read=True,
)
Expand Down
15 changes: 14 additions & 1 deletion candore/modules/extractor.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import asyncio # noqa: F401
from functools import cached_property

from candore.modules.ssh import Session
import re
import aiohttp


Expand Down Expand Up @@ -157,3 +158,15 @@ async def extract_all_entities(self):
comp_entities = await self.process_entities(endpoints=endpoints)
all_data[component] = comp_entities
return all_data

async def extract_all_rpms(self):
"""Extracts all installed RPMs from server"""
with Session() as ssh_client:
rpms = ssh_client.execute('rpm -qa').stdout
rpms = rpms.splitlines()
name_version_pattern = rf'{self.settings.rpms.regex_pattern}'
rpms_matches = [
re.compile(name_version_pattern).match(rpm) for rpm in rpms
]
rpms_list = [rpm_match.groups()[:-1] for rpm_match in rpms_matches if rpm_match]
return dict(rpms_list)
64 changes: 64 additions & 0 deletions candore/modules/ssh.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from hussh import Connection
from pathlib import Path
from functools import cached_property
from candore.config import candore_settings
from urllib.parse import urlparse


class SSHClient:

def __init__(self, **kwargs):
hostname = kwargs.get("hostname", "localhost")
username = kwargs.get("username", "root")
port = kwargs.get("port", 22)
timeout = kwargs.get("timeout", 60) * 1000

private_key = kwargs.get("private_key")
password = kwargs.get("password")

client_kwargs = {"username": username, "port": port, "timeout": timeout}

try:
if private_key:
if not Path(private_key).exists():
raise FileNotFoundError(f"The private key does not exists at path {private_key}")
client_kwargs["private_key"] = private_key
elif password:
client_kwargs["password"] = password
else:
raise ConnectionError("Keyfile or password is not provided for ssh connection")

self.client = Connection(hostname, **client_kwargs)

except Exception as err:
raise ConnectionError(
f"SSH Connection failed."
) from err

def execute(self, command):
result = self.client.execute(command)
return result


class Session:

def __init__(self):
self.settings = candore_settings()
self.hostname = urlparse(self.settings.candore.base_url).hostname
self.username = self.settings.candore.ssh.username

@cached_property
def auth(self):
auth_kwargs = {}
if self.settings.candore.ssh.private_key:
auth_kwargs["private_key"] = self.settings.candore.ssh.private_key
elif self.settings.candore.ssh.password:
auth_kwargs["password"] = self.settings.candore.ssh.password
return auth_kwargs

def __enter__(self):
self.client = SSHClient(username=self.username, hostname=self.hostname, **self.auth).client
return self.client

def __exit__(self, exc_type, exc_val, exc_tb):
pass
2 changes: 2 additions & 0 deletions conf/rpms.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
rpms:
regex_pattern: '([a-zA-Z0-9_-]+)-([\d._-]+)\.(.*?)$'
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ dependencies = [
"flask",
"requests",
"PyYAML",
"hussh",
]

[project.optional-dependencies]
Expand Down
2 changes: 2 additions & 0 deletions settings.yaml.template
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ candore:
parser: apipie
var_file: "@jinja {{this.candore.product_version | replace('.', '_')}}_variations.yaml"
constant_File: "@jinja {{this.candore.product_version | replace('.', '_')}}_constants.yaml"
custom:
- rpms

0 comments on commit bd93fcd

Please sign in to comment.