-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into dependabot/go_modules/acs-export-example/gol…
…ang.org/x/net-0.23.0
- Loading branch information
Showing
15 changed files
with
44,508 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
FROM registry.access.redhat.com/ubi9:9.1.0-1782 | ||
|
||
# #ENV Variables | ||
# ENV APP_MODULE testapp:app | ||
# ENV APP_CONFIG gunicorn.conf.py | ||
|
||
#Change User | ||
USER 0 | ||
|
||
# Install the required software | ||
RUN dnf install -y wget yum-utils make gcc openssl-devel bzip2-devel libffi-devel zlib-devel && \ | ||
wget https://www.python.org/ftp/python/3.10.8/Python-3.10.8.tgz && \ | ||
tar xzf Python-3.10.8.tgz && \ | ||
cd Python-3.10.8 && \ | ||
./configure --with-system-ffi --with-computed-gotos --enable-loadable-sqlite-extensions && \ | ||
make altinstall && \ | ||
cd .. && \ | ||
rm Python-3.10.8.tgz | ||
|
||
# # Install pip | ||
# RUN curl -O https://bootstrap.pypa.io/get-pip.py && python3 get-pip.py && python3 get-pip.py | ||
|
||
#Make Application Directory | ||
RUN mkdir ./app && cd ./app && echo python -V | ||
|
||
# Copy Files into containers | ||
COPY ./ ./app | ||
|
||
#WORKDIR | ||
WORKDIR ./app | ||
|
||
#Install App Dependecies | ||
RUN pip3.10 install -r requirements.txt && pip3.10 install --upgrade pip | ||
|
||
#Expose Ports | ||
EXPOSE 8080/tcp | ||
|
||
#Change Permissions to allow not root-user work | ||
RUN chmod -R g+rw ./ | ||
|
||
#Change User | ||
USER 1001 | ||
|
||
#ENTRY | ||
ENTRYPOINT python3.10 app.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Prototype application to parse multiple ACS endpoints collect metadata via the API, correlate data and parse out JSON files. | ||
- Will parse out a hierarchical Cluster->Namespace->Deployment->Alerts Relationship | ||
- Can be extended to parse out other relationships | ||
|
||
# Configuration | ||
- Configuration settings are mostly obtained from enviromnent variables. Configuration settings are provided and explained in [config file](./config.py) | ||
|
||
- The list of endpoints for the app to poll can be set via ENDPOINT_LIST_JSON_PATH environment variable. The environment variable should point to a json file with API details. A sample file is provided in [endpoint_list.json](./endpoint_list.json).While environment details are provided via the previously mentioned variable the token used for connection is obtained via enviroment variable. And the token environment variable must be set in the endpoint json file and defined by field "endpoint_token_env_variable_name". | ||
|
||
- Generate's sample output files in output folder, but can be customized for other use cases. | ||
- cluster_namespace_deployment_alert.json: JSON file with hierarchical Cluster->Namespace->Deployment->Alerts relationship. | ||
- endpoint_policy_alert_count.json: JSON file with ACS Endpoint -> Policy -> AlertCount Relationship | ||
|
||
# Run with Podman | ||
- Build Image | ||
```bash | ||
podman build -t quick_acs_app . | ||
``` | ||
|
||
- Run Container | ||
```bash | ||
podman run --env $MAIN_ACS_TOKEN --env OUTPUT_FOLDER=/output -v /tmp/output:/output:Z localhost/quick_acs_app | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
from httpx import AsyncClient,HTTPError,NetworkError,RequestError,TimeoutException,ConnectTimeout,InvalidURL,ProtocolError,ConnectError | ||
import os | ||
from httpx._config import SSLConfig | ||
from logging import getLogger, config | ||
import typing as t | ||
import asyncio | ||
|
||
|
||
import logging | ||
try: | ||
logger = getLogger("logger_root") | ||
except: | ||
logger = logging.getLogger(__name__) | ||
|
||
class PaginationCounter: | ||
|
||
def __init__(self, total_count, limit): | ||
|
||
self.limit = limit | ||
if not total_count: | ||
raise ValueError("total_count value should be specified") | ||
if not self.limit: | ||
raise ValueError("limit value should be specified") | ||
self.end = total_count | ||
self.start = 0 - self.limit | ||
|
||
def __iter__(self): | ||
return self | ||
|
||
def __next__(self): | ||
if self.start < self.end: | ||
if self.start + self.limit > self.end: | ||
self.start=self.end | ||
else: | ||
self.start += self.limit | ||
return self.start | ||
else: | ||
raise StopIteration | ||
|
||
|
||
async def make_request(full_url_path,insecure:bool=False,headers:dict=None,params:dict=None,offset=None) -> dict: | ||
"""Make a request to the API""" | ||
error=None | ||
response=None | ||
|
||
#TODO: Clean offset and params | ||
if offset is not None: | ||
params["pagination.offset"] = offset | ||
|
||
try: | ||
async with AsyncClient(verify=insecure) as client: | ||
response = await client.get( | ||
f"{full_url_path}",headers=headers,params=params | ||
) | ||
logger.debug(f"request_processing - attempted request") | ||
response.raise_for_status() | ||
except ConnectTimeout as timeout_err: | ||
logger.error(f" Connect Timeout error occurred: {timeout_err}") | ||
error=f"Connect Timeout error occurred: {timeout_err}" | ||
except NetworkError as network_err: | ||
logger.error(f"Network error occurred: {network_err}") | ||
error=f"Network error occurred: {network_err}" | ||
except TimeoutException as timeout_err: | ||
logger.error(f"Timeout error occurred: {timeout_err}") | ||
error=f"Timeout error occurred: {timeout_err}" | ||
except RequestError as req_err: | ||
logger.error(f"Error occurred while processing request: {req_err}") | ||
error=f"Error occurred while processing request: {req_err}" | ||
except InvalidURL as url_err: | ||
logger.error(f"Invalid URL error occurred: {url_err}") | ||
error=f"Invalid URL error occurred: {url_err}" | ||
except HTTPError as http_err: | ||
logger.error(f"HTTP error occurred: {http_err}") | ||
error=f"HTTP error occurred: {http_err}" | ||
except IOError as e: | ||
logger.error("I/O error({0}): {1}".format(e.errno, e.strerror)) | ||
except BaseException as e: | ||
print("Something serious has occured") | ||
error=f"Something Seriously unexpected has occured" | ||
|
||
return {"response_object":response,"error_object":error} | ||
|
||
async def request_processing_pagination(full_url_path,insecure:bool=False,headers:dict=None,params:dict=None): | ||
""" | ||
Args: | ||
full_url_path (_type_): ACS URL with path for the request | ||
insecure (bool, optional): Make an insecure Request, Should be set from verify_endpoint_ssl on endpoint object | ||
headers (dict, optional): Headers for Request to ACS. Defaults to None. | ||
params (dict, optional): Parameters for Request to ACS. Defaults to None. | ||
""" | ||
|
||
try: | ||
total_expected_count = params["pagination.total_expected_count"] | ||
del params["pagination.total_expected_count"] | ||
except KeyError as error: | ||
logger.error(f"pagination.total_expected_count not found in params,Method is only for paginated requests") | ||
return | ||
|
||
if total_expected_count == 0: | ||
logger.error(f"pagination.total_expected_count is 0,Method is only for paginated requests") | ||
return | ||
|
||
if "pagination.limit" not in params: | ||
logger.error(f"pagination.limit not found in params,Method is only for paginated requests") | ||
return | ||
|
||
if "pagination.offset" not in params: | ||
params["pagination.offset"] = 0 | ||
|
||
if total_expected_count is None: | ||
logger.error(f"pagination.total_expected_count not found in params,Method is only for paginated requests") | ||
return | ||
|
||
#TODO: Requires streamline for offset and params | ||
response_dict={"response_object":[],"error_object":None} | ||
for offset in PaginationCounter(total_expected_count,params["pagination.limit"]): | ||
params.update({"pagination.offset":offset}) | ||
temp_dict = await make_request(full_url_path,insecure,headers,params) | ||
|
||
if temp_dict["error_object"] is not None: | ||
return temp_dict["error_object"] | ||
else: | ||
response_dict["response_object"].append(temp_dict["response_object"]) | ||
return response_dict | ||
|
||
async def request_processing(full_url_path,insecure:bool=False,headers:dict=None,params:dict=None) -> dict: | ||
"""Send the Request and process the response""" | ||
logger.debug(f"request_processing -start: url:{full_url_path} verify_ssl:{insecure}") | ||
error=None | ||
|
||
if params is None: | ||
response_dict = await make_request(full_url_path,insecure,headers,params) | ||
else: | ||
if "pagination.limit" in params and "total_expected_count" in params: | ||
response_dict = await request_processing_pagination(full_url_path,insecure,headers,params) | ||
else: | ||
response_dict = await make_request(full_url_path,insecure,headers,params) | ||
return response_dict | ||
|
||
async def get_acs_alert(url,alert_id: str,insecure:bool=False,headers:dict=None,params:dict=None) -> dict: | ||
"""Get ACS alert from the API""" | ||
if alert_id is not None: | ||
logger.debug(f"get_acs_alert -start: url:{url} id:{alert_id} verify_ssl:{insecure}") | ||
rhacs_alert_url_path=f"{url}/v1/alerts/{alert_id}" | ||
else: | ||
logger.debug(f"get_acs_alert -start: url:{url} verify_ssl:{insecure}") | ||
rhacs_alert_url_path=f"{url}/v1/alerts" | ||
response_dict = await request_processing(rhacs_alert_url_path,insecure,headers,params) | ||
logger.debug(f"get_acs_alert - complete") | ||
return response_dict | ||
|
||
async def get_policy(url,insecure:bool=False,headers:dict=None,params:dict=None) -> dict: | ||
"""Get Policy from the API""" | ||
logger.debug(f"get_policy -start: url:{url} verify_ssl:{insecure}") | ||
rhacs_policy_url_path=f"{url}/v1/policies" | ||
response_dict = await request_processing(rhacs_policy_url_path,insecure,headers,params) | ||
logger.debug(f"get_policy - complete") | ||
return response_dict | ||
|
||
async def get_alert_count(url,insecure:bool=False,headers:dict=None,params:dict=None) -> dict: | ||
"""Get Alert Count""" | ||
logger.debug(f"get_policy -start: url:{url} verify_ssl:{insecure}") | ||
rhacs_policy_url_path=f"{url}/v1/alertscount" | ||
response_dict = await request_processing(rhacs_policy_url_path,insecure,headers,params) | ||
logger.debug(f"get_policy - complete") | ||
return response_dict | ||
|
||
async def get_acs_deployment(url,deployment_id:str, insecure:bool=False,headers:dict=None,params:dict=None) -> dict: | ||
"""Get Deployment from the API""" | ||
if deployment_id is not None: | ||
logger.debug(f"get_acs_alert -start: url:{url} id:{deployment_id} verify_ssl:{insecure}") | ||
rhacs_deployment_url_path=f"{url}/v1/deployments/{deployment_id}" | ||
else: | ||
logger.debug(f"get_acs_alert -start: url:{url} verify_ssl:{insecure}") | ||
rhacs_deployment_url_path=f"{url}/v1/deployments" | ||
|
||
logger.debug(f"get_deployment -start: url:{url}") | ||
response_dict = await request_processing(rhacs_deployment_url_path,insecure,headers,params) | ||
logger.debug(f"get_deployment - complete") | ||
return response_dict | ||
|
||
async def get_rhacs_health(url,insecure:bool=False,headers:dict=None,params:dict=None) -> dict: | ||
"""Get health from the API""" | ||
logger.debug(f"get_rhacs_health -start: url:{url}") | ||
rhacs_health_url_path=f"{url}/v1/ping" | ||
response_dict = await request_processing(rhacs_health_url_path,insecure,headers,params) | ||
logger.debug(f"get_rhacs_health - complete") | ||
return response_dict |
Oops, something went wrong.