Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/go_modules/acs-export-example/gol…
Browse files Browse the repository at this point in the history
…ang.org/x/net-0.23.0
  • Loading branch information
srcporter authored Jul 8, 2024
2 parents 92691e1 + ca1b021 commit a2c45bf
Show file tree
Hide file tree
Showing 15 changed files with 44,508 additions and 7 deletions.
4 changes: 2 additions & 2 deletions acs-export-example/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ require (
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-hclog v1.5.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
Expand Down Expand Up @@ -171,7 +171,7 @@ require (
golang.org/x/net v0.23.0 // indirect
golang.org/x/oauth2 v0.18.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.stackrox.io/grpc-http1 v0.3.9 // indirect
Expand Down
7 changes: 2 additions & 5 deletions acs-export-example/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -404,14 +404,11 @@ github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
Expand Down Expand Up @@ -771,8 +768,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
Expand Down
45 changes: 45 additions & 0 deletions util-scripts/acs-correlation-example/Dockerfile
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
23 changes: 23 additions & 0 deletions util-scripts/acs-correlation-example/README.md
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
```
189 changes: 189 additions & 0 deletions util-scripts/acs-correlation-example/acs_request.py
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
Loading

0 comments on commit a2c45bf

Please sign in to comment.