Skip to content

Commit

Permalink
ARTESCA-11245 repair metalk8s monitoring salt module
Browse files Browse the repository at this point in the history
  • Loading branch information
aprucolimartins committed Feb 26, 2024
1 parent d59ffbb commit 97feea2
Show file tree
Hide file tree
Showing 8 changed files with 290 additions and 36 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@
Workload Plane/Control Plane CIDRs.
(PR[#4217](https://github.com/scality/metalk8s/pull/4217))

### Bug fixes

- Salt module metalk8s_monitoring fixed and improved
(PR[#4238](https://github.com/scality/metalk8s/pull/4238))

## Release 126.0.2

### Bug fixes

- [2137](https://github.com/scality/metalk8s/issues/2137) - Fix a bug
that prevents re-run of the bootstrap script if it fails at a specific point
(PR[4196](https://github.com/scality/metalk8s/pull/4196))
(PR[#4196](https://github.com/scality/metalk8s/pull/4196))

- Bump the attempts to wait for the Operator and ClusterConfig
to be Ready
Expand Down
59 changes: 57 additions & 2 deletions salt/_modules/metalk8s_kubernetes_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def read_and_render_yaml_file(source, template, context=None, saltenv="base"):
return salt.utils.yaml.safe_load(contents)


def get_service_endpoints(service, namespace, kubeconfig):
def get_service_endpoints(service, namespace, **kwargs):
error_tpl = "Unable to get kubernetes endpoints for {} in namespace {}"

try:
Expand All @@ -159,7 +159,7 @@ def get_service_endpoints(service, namespace, kubeconfig):
kind="Endpoints",
apiVersion="v1",
namespace=namespace,
kubeconfig=kubeconfig,
**kwargs,
)
if not endpoint:
raise CommandExecutionError("Endpoint not found")
Expand All @@ -184,3 +184,58 @@ def get_service_endpoints(service, namespace, kubeconfig):
raise CommandExecutionError(error_tpl.format(service, namespace)) from exc

return result


def get_service_ips_and_ports(service, namespace, **kwargs):
try:
service_object = __salt__["metalk8s_kubernetes.get_object"](
name=service,
kind="Service",
apiVersion="v1",
namespace=namespace,
**kwargs,
)
if not service_object:
raise CommandExecutionError("Service not found")
except CommandExecutionError as exc:
raise CommandExecutionError(
f"Unable to get kubernetes service {service} in namespace {namespace}"
) from exc

cip = service_object["spec"].get("clusterIP")
cips = [cip] if cip else []
cips.extend(
[ip for ip in service_object["spec"].get("clusterIPs", []) if ip != cip]
)

try:
unamed = 0
ports = {}
service_ports = service_object["spec"]["ports"]

for port in service_ports:
if port.get("name"):
ports[port["name"]] = port["port"]
else:
ports[f"unnamed-{unamed}"] = port["port"]
unamed += 1

if not ports:
raise CommandExecutionError("No ports")
except (
AttributeError,
IndexError,
KeyError,
TypeError,
CommandExecutionError,
) as exc:
raise CommandExecutionError(
f"No ports for service {service} in namespace {namespace}",
) from exc

result = {}
if cips:
result["ips"] = cips
result["ports"] = ports

return result
40 changes: 21 additions & 19 deletions salt/_modules/metalk8s_monitoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

def __virtual__():
if MISSING_DEPS:
error_msg = "Missing dependencies: {}".format(", ".join(MISSING_DEPS))
error_msg = f"Missing dependencies: {', '.join(MISSING_DEPS)}"
return False, error_msg

return __virtualname__
Expand All @@ -33,7 +33,7 @@ def add_silence(
time_format="%Y-%m-%dT%H:%M:%S",
author="",
comment="",
**kwargs
**kwargs,
):
"""Add a new silence in Alertmanager.
Expand Down Expand Up @@ -106,9 +106,7 @@ def delete_silence(silence_id, **kwargs):
salt-call metalk8s_monitoring.delete_silence \
64d84a9e-cc6e-41ce-83ff-e84771ff6872
"""
_requests_alertmanager_api(
"api/v1/silence/{}".format(silence_id), "DELETE", **kwargs
)
_requests_alertmanager_api(f"api/v1/silence/{silence_id}", "DELETE", **kwargs)


def get_silences(state=None, **kwargs):
Expand Down Expand Up @@ -164,42 +162,46 @@ def get_alerts(state=None, **kwargs):


def _requests_alertmanager_api(route, method="GET", **kwargs):
endpoint = __salt__["metalk8s_kubernetes.get_service_endpoints"](
endpoints = __salt__["metalk8s_kubernetes.get_service_ips_and_ports"](
"prometheus-operator-alertmanager",
"metalk8s-monitoring",
kwargs.pop("kubeconfig", None),
**kwargs,
)

url = "http://{}:{}/{}".format(
endpoint["ip"],
endpoint["ports"]["web"],
route,
)
try:
ip = endpoints["ips"][0]
port = endpoints["ports"]["http-web"]
url = f"http://{ip}:{port}/{route}"
except (IndexError, KeyError) as exc:
raise CommandExecutionError(
"Unable to get proper Alertmanager API endpoint: "
f"Available endpoints: {endpoints}"
) from exc

try:
session = __utils__["metalk8s.requests_retry_session"]()
response = session.request(method, url, **kwargs)
except Exception as exc:
raise CommandExecutionError(
"Unable to query Alertmanager API on {}".format(url)
f"Unable to query Alertmanager API on {url}"
) from exc

try:
json = response.json()
except ValueError as exc:
if response.status_code != requests.codes.ok:
error = "Received HTTP code {} when querying Alertmanager API on {}".format(
response.status_code, url
error = (
f"Received HTTP code {response.status_code} when "
f"querying Alertmanager API on {url}"
)
else:
error = (
"Malformed response returned from Alertmanager API: {!s}: {}".format(
exc, response.text
)
"Malformed response returned from Alertmanager API: "
f"{exc}: {response.text}"
)
raise CommandExecutionError(error) from exc

if json["status"] == "error":
raise CommandExecutionError("{}: {}".format(json["errorType"], json["error"]))
raise CommandExecutionError(f"{json['errorType']}: {json['error']}")

return json.get("data")
2 changes: 1 addition & 1 deletion salt/_pillar/metalk8s_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def ext_pillar(minion_id, pillar, kubeconfig): # pylint: disable=unused-argumen
try:
service_endpoints = __salt__[
"metalk8s_kubernetes.get_service_endpoints"
](service, namespace, kubeconfig)
](service, namespace, kubeconfig=kubeconfig)
except CommandExecutionError as exc:
errors.append(str(exc))

Expand Down
129 changes: 129 additions & 0 deletions salt/tests/unit/modules/files/test_metalk8s_kubernetes_utils.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -278,3 +278,132 @@ get_service_endpoints:
subsets: null
raises: True
result: "Unable to get kubernetes endpoints for my_service in namespace my_namespace"

get_service_ips_and_ports:
# Multiples IPs and multiple ports
- obj:
spec:
clusterIPs:
- 10.0.0.1
- 10.0.0.2
clusterIP: 10.0.0.1
ports:
- name: http-web
port: 1234
- name: reloader-web
port: 1235
result:
ips:
- 10.0.0.1
- 10.0.0.2
ports:
http-web: 1234
reloader-web: 1235
# ClusterIP not in clusterIPs and multiple ports
- obj:
spec:
clusterIPs:
- 10.0.0.2
- 10.0.0.3
clusterIP: 10.0.0.1
ports:
- name: http-web
port: 1234
- name: reloader-web
port: 1235
result:
ips:
- 10.0.0.1
- 10.0.0.2
- 10.0.0.3
ports:
http-web: 1234
reloader-web: 1235
# Single IP and multiple ports
- obj:
spec:
clusterIPs:
- 10.0.0.1
clusterIP: 10.0.0.1
ports:
- name: http-web
port: 2345
- name: reloader-web
port: 2346
result:
ips:
- 10.0.0.1
ports:
http-web: 2345
reloader-web: 2346
# Only clusterIP and multiple ports
- obj:
spec:
clusterIP: 10.0.0.1
ports:
- name: http-web
port: 2345
- name: reloader-web
port: 2346
result:
ips:
- 10.0.0.1
ports:
http-web: 2345
reloader-web: 2346
# No IPs and multiple ports
- obj:
spec:
ports:
- name: http-web
port: 1234
- name: reloader-web
port: 1235
result:
ports:
http-web: 1234
reloader-web: 1235
# Named and unnamed ports
- obj:
spec:
ports:
- name: http-web
port: 1234
- port: 1235
result:
ports:
http-web: 1234
unnamed-0: 1235
# Unnamed ports
- obj:
spec:
ports:
- port: 1234
- port: 1235
result:
ports:
unnamed-0: 1234
unnamed-1: 1235
# No ports
- obj:
spec:
ports: []
result: "No ports for service my_service in namespace my_namespace"
raises: True
# Empty spec
- obj:
spec: {}
result: "No ports for service my_service in namespace my_namespace"
raises: True
# Empty object returned
- obj: {}
result: "Unable to get kubernetes service my_service in namespace my_namespace"
raises: True
# Object is False
- obj: False
result: "Unable to get kubernetes service my_service in namespace my_namespace"
raises: True
# No object returned
- obj: null
result: "Unable to get kubernetes service my_service in namespace my_namespace"
raises: True

0 comments on commit 97feea2

Please sign in to comment.