Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion codebundles/k8s-daemonset-healthcheck/runbook.robot
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ Analyze Application Log Patterns for DaemonSet `${DAEMONSET_NAME}` in Namespace
... context=${CONTEXT}
... kubeconfig=${kubeconfig}
... log_age=${LOG_AGE}
... excluded_containers=${EXCLUDED_CONTAINERS}

${scan_results}= RW.K8sLog.Scan Logs For Issues
... log_dir=${log_dir}
... workload_type=daemonset
... workload_name=${DAEMONSET_NAME}
... namespace=${NAMESPACE}
... categories=@{LOG_PATTERN_CATEGORIES}
... excluded_containers=${EXCLUDED_CONTAINERS}

${log_health_score}= RW.K8sLog.Calculate Log Health Score scan_results=${scan_results}

Expand Down Expand Up @@ -98,12 +100,14 @@ Detect Log Anomalies for DaemonSet `${DAEMONSET_NAME}` in Namespace `${NAMESPACE
... context=${CONTEXT}
... kubeconfig=${kubeconfig}
... log_age=${LOG_AGE}
... excluded_containers=${EXCLUDED_CONTAINERS}

${anomaly_results}= RW.K8sLog.Analyze Log Anomalies
... log_dir=${log_dir}
... workload_type=daemonset
... workload_name=${DAEMONSET_NAME}
... namespace=${NAMESPACE}
... excluded_containers=${EXCLUDED_CONTAINERS}

# Process anomaly issues
${anomaly_issues}= Evaluate $anomaly_results.get('issues', [])
Expand Down Expand Up @@ -945,9 +949,21 @@ Suite Initialization
... pattern=\d+
... example=1
... default=1
${EXCLUDED_CONTAINER_NAMES}= RW.Core.Import User Variable EXCLUDED_CONTAINER_NAMES
... type=string
... description=Comma-separated list of container names to exclude from log analysis (e.g., linkerd-proxy, istio-proxy, vault-agent).
... pattern=.*
... example=linkerd-proxy,istio-proxy,vault-agent
... default=linkerd-proxy,istio-proxy,vault-agent

# Convert comma-separated string to list
# Convert comma-separated strings to lists
@{LOG_PATTERN_CATEGORIES}= Split String ${LOG_PATTERN_CATEGORIES_STR} ,
@{EXCLUDED_CONTAINERS_RAW}= Run Keyword If "${EXCLUDED_CONTAINER_NAMES}" != "" Split String ${EXCLUDED_CONTAINER_NAMES} , ELSE Create List
@{EXCLUDED_CONTAINERS}= Create List
FOR ${container} IN @{EXCLUDED_CONTAINERS_RAW}
${trimmed_container}= Strip String ${container}
Append To List ${EXCLUDED_CONTAINERS} ${trimmed_container}
END

Set Suite Variable ${kubeconfig}
Set Suite Variable ${KUBERNETES_DISTRIBUTION_BINARY}
Expand All @@ -961,6 +977,8 @@ Suite Initialization
Set Suite Variable ${ANOMALY_THRESHOLD}
Set Suite Variable ${CONTAINER_RESTART_AGE}
Set Suite Variable ${CONTAINER_RESTART_THRESHOLD}
Set Suite Variable ${EXCLUDED_CONTAINER_NAMES}
Set Suite Variable @{EXCLUDED_CONTAINERS}
${env}= Evaluate {"KUBECONFIG":"${kubeconfig.key}","KUBERNETES_DISTRIBUTION_BINARY":"${KUBERNETES_DISTRIBUTION_BINARY}","CONTEXT":"${CONTEXT}","NAMESPACE":"${NAMESPACE}","DAEMONSET_NAME":"${DAEMONSET_NAME}","CONTAINER_RESTART_AGE":"${CONTAINER_RESTART_AGE}","CONTAINER_RESTART_THRESHOLD":"${CONTAINER_RESTART_THRESHOLD}"}
Set Suite Variable ${env}

Expand Down
47 changes: 43 additions & 4 deletions codebundles/k8s-deployment-healthcheck/runbook.robot
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ Suite Initialization
... pattern=.*
... example=linkerd-proxy,istio-proxy,vault-agent
... default=linkerd-proxy,istio-proxy,vault-agent
${CONTAINER_NAME}= RW.Core.Import User Variable CONTAINER_NAME
... type=string
... description=Optional: the specific container name to fetch logs from. If not set, the primary application container is auto-detected by excluding known sidecars.
... pattern=.*
... example=controller
... default=

${CONTAINER_RESTART_AGE}= RW.Core.Import User Variable CONTAINER_RESTART_AGE
... type=string
Expand Down Expand Up @@ -152,6 +158,7 @@ Suite Initialization
Set Suite Variable ${LOG_SCAN_TIMEOUT}
Set Suite Variable ${EXCLUDED_CONTAINER_NAMES}
Set Suite Variable @{EXCLUDED_CONTAINERS}
Set Suite Variable ${CONTAINER_NAME}

Set Suite Variable ${CONTAINER_RESTART_AGE}
Set Suite Variable ${CONTAINER_RESTART_THRESHOLD}
Expand Down Expand Up @@ -401,9 +408,41 @@ Fetch Deployment Logs for `${DEPLOYMENT_NAME}` in Namespace `${NAMESPACE}`
... data:logs-bulk
# Skip pod-related checks if deployment is scaled to 0
IF not ${SKIP_POD_CHECKS}
# Fetch raw logs
# Determine which container to fetch logs from
IF "${CONTAINER_NAME}" != ""
${target_container}= Set Variable ${CONTAINER_NAME}
ELSE
# Auto-detect primary container by listing containers and excluding known sidecars
${container_json}= RW.CLI.Run Cli
... cmd=${KUBERNETES_DISTRIBUTION_BINARY} get deployment/${DEPLOYMENT_NAME} --context ${CONTEXT} -n ${NAMESPACE} -o jsonpath='{.spec.template.spec.containers[*].name}'
... env=${env}
... secret_file__kubeconfig=${kubeconfig}
... include_in_history=false
@{all_containers}= Split String ${container_json.stdout}
${container_count}= Get Length ${all_containers}
${target_container}= Set Variable ${EMPTY}
IF ${container_count} > 0
FOR ${cname} IN @{all_containers}
${is_excluded}= Evaluate "${cname}" in ${EXCLUDED_CONTAINERS}
IF not ${is_excluded}
${target_container}= Set Variable ${cname}
BREAK
END
END
IF "${target_container}" == ""
${target_container}= Set Variable ${all_containers}[0]
END
END
END

# Build the kubectl logs command with or without -c flag
IF "${target_container}" != ""
${logs_cmd}= Set Variable ${KUBERNETES_DISTRIBUTION_BINARY} logs deployment/${DEPLOYMENT_NAME} -c ${target_container} --context ${CONTEXT} -n ${NAMESPACE} --tail=${LOG_LINES} --since=${LOG_AGE}
ELSE
${logs_cmd}= Set Variable ${KUBERNETES_DISTRIBUTION_BINARY} logs deployment/${DEPLOYMENT_NAME} --context ${CONTEXT} -n ${NAMESPACE} --tail=${LOG_LINES} --since=${LOG_AGE}
END
${deployment_logs}= RW.CLI.Run Cli
... cmd=${KUBERNETES_DISTRIBUTION_BINARY} logs deployment/${DEPLOYMENT_NAME} --context ${CONTEXT} -n ${NAMESPACE} --tail=${LOG_LINES} --since=${LOG_AGE}
... cmd=${logs_cmd}
... env=${env}
... secret_file__kubeconfig=${kubeconfig}
... show_in_rwl_cheatsheet=true
Expand All @@ -412,13 +451,13 @@ Fetch Deployment Logs for `${DEPLOYMENT_NAME}` in Namespace `${NAMESPACE}`
IF ${deployment_logs.returncode} == 0
# Filter logs to remove repetitive health check messages and focus on meaningful content
${filtered_logs}= RW.CLI.Run Cli
... cmd=echo "${deployment_logs.stdout}" | grep -v -E "(Checking.*Health|Health.*Check|healthcheck|/health|GET /|POST /health|probe|liveness|readiness)" | grep -E "(error|ERROR|warn|WARN|exception|Exception|fail|FAIL|fatal|FATAL|panic|stack|trace|timeout|connection.*refused|unable.*connect|authentication.*failed|denied|forbidden|unauthorized|500|502|503|504)" | tail -50 || echo "No significant errors or warnings found in recent logs"
... cmd=echo "${deployment_logs.stdout}" | grep -v -E "(Checking.*Health|Health.*Check|healthcheck|/health|GET /health|POST /health|probe|liveness|readiness)" | grep -E "(error|ERROR|warn|WARN|exception|Exception|fail|FAIL|fatal|FATAL|panic|stack|trace|timeout|connection.*refused|unable.*connect|authentication.*failed|denied|forbidden|unauthorized|500|502|503|504)" | tail -50 || echo "No significant errors or warnings found in recent logs"
... env=${env}
... include_in_history=false

# Also get a sample of non-health-check logs for context
${context_logs}= RW.CLI.Run Cli
... cmd=echo "${deployment_logs.stdout}" | grep -v -E "(Checking.*Health|Health.*Check|healthcheck|/health|GET /|POST /health|probe|liveness|readiness)" | head -20 | tail -10
... cmd=echo "${deployment_logs.stdout}" | grep -v -E "(Checking.*Health|Health.*Check|healthcheck|/health|GET /health|POST /health|probe|liveness|readiness)" | head -20 | tail -10
... env=${env}
... include_in_history=false

Expand Down
7 changes: 6 additions & 1 deletion codebundles/k8s-stacktrace-health/runbook.robot
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,12 @@ Analyze Workload Stacktraces for ${WORKLOAD_TYPE} `${WORKLOAD_NAME}` in Namespac
# Skip pod-related checks if workload is scaled to 0
IF not ${SKIP_STACKTRACE_CHECKS}
# Convert comma-separated string to list for excluded containers
@{EXCLUDED_CONTAINERS}= Run Keyword If "${EXCLUDED_CONTAINER_NAMES}" != "" Split String ${EXCLUDED_CONTAINER_NAMES} , ELSE Create List
@{EXCLUDED_CONTAINERS_RAW}= Run Keyword If "${EXCLUDED_CONTAINER_NAMES}" != "" Split String ${EXCLUDED_CONTAINER_NAMES} , ELSE Create List
@{EXCLUDED_CONTAINERS}= Create List
FOR ${container} IN @{EXCLUDED_CONTAINERS_RAW}
${trimmed_container}= Strip String ${container}
Append To List ${EXCLUDED_CONTAINERS} ${trimmed_container}
END

# Fetch logs using RW.K8sLog library (same pattern as deployment healthcheck)
${log_dir}= RW.K8sLog.Fetch Workload Logs
Expand Down
7 changes: 6 additions & 1 deletion codebundles/k8s-stacktrace-health/sli.robot
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,12 @@ Suite Initialization


# Convert comma-separated string to list
@{EXCLUDED_CONTAINERS}= Run Keyword If "${EXCLUDED_CONTAINER_NAMES}" != "" Split String ${EXCLUDED_CONTAINER_NAMES} , ELSE Create List
@{EXCLUDED_CONTAINERS_RAW}= Run Keyword If "${EXCLUDED_CONTAINER_NAMES}" != "" Split String ${EXCLUDED_CONTAINER_NAMES} , ELSE Create List
@{EXCLUDED_CONTAINERS}= Create List
FOR ${container} IN @{EXCLUDED_CONTAINERS_RAW}
${trimmed_container}= Strip String ${container}
Append To List ${EXCLUDED_CONTAINERS} ${trimmed_container}
END
Set Suite Variable @{EXCLUDED_CONTAINERS}

# Initialize score variables
Expand Down
20 changes: 19 additions & 1 deletion codebundles/k8s-statefulset-healthcheck/runbook.robot
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ Analyze Application Log Patterns for StatefulSet `${STATEFULSET_NAME}` in Namesp
... context=${CONTEXT}
... kubeconfig=${kubeconfig}
... log_age=${LOG_AGE}
... excluded_containers=${EXCLUDED_CONTAINERS}

${scan_results}= RW.K8sLog.Scan Logs For Issues
... log_dir=${log_dir}
... workload_type=statefulset
... workload_name=${STATEFULSET_NAME}
... namespace=${NAMESPACE}
... categories=@{LOG_PATTERN_CATEGORIES}
... excluded_containers=${EXCLUDED_CONTAINERS}

${log_health_score}= RW.K8sLog.Calculate Log Health Score scan_results=${scan_results}

Expand Down Expand Up @@ -99,12 +101,14 @@ Detect Log Anomalies for StatefulSet `${STATEFULSET_NAME}` in Namespace `${NAMES
... context=${CONTEXT}
... kubeconfig=${kubeconfig}
... log_age=${LOG_AGE}
... excluded_containers=${EXCLUDED_CONTAINERS}

${anomaly_results}= RW.K8sLog.Analyze Log Anomalies
... log_dir=${log_dir}
... workload_type=statefulset
... workload_name=${STATEFULSET_NAME}
... namespace=${NAMESPACE}
... excluded_containers=${EXCLUDED_CONTAINERS}

# Process anomaly issues
${anomaly_issues}= Evaluate $anomaly_results.get('issues', [])
Expand Down Expand Up @@ -970,9 +974,21 @@ Suite Initialization
... pattern=\d+
... example=1
... default=1
${EXCLUDED_CONTAINER_NAMES}= RW.Core.Import User Variable EXCLUDED_CONTAINER_NAMES
... type=string
... description=Comma-separated list of container names to exclude from log analysis (e.g., linkerd-proxy, istio-proxy, vault-agent).
... pattern=.*
... example=linkerd-proxy,istio-proxy,vault-agent
... default=linkerd-proxy,istio-proxy,vault-agent

# Convert comma-separated string to list
# Convert comma-separated strings to lists
@{LOG_PATTERN_CATEGORIES}= Split String ${LOG_PATTERN_CATEGORIES_STR} ,
@{EXCLUDED_CONTAINERS_RAW}= Run Keyword If "${EXCLUDED_CONTAINER_NAMES}" != "" Split String ${EXCLUDED_CONTAINER_NAMES} , ELSE Create List
@{EXCLUDED_CONTAINERS}= Create List
FOR ${container} IN @{EXCLUDED_CONTAINERS_RAW}
${trimmed_container}= Strip String ${container}
Append To List ${EXCLUDED_CONTAINERS} ${trimmed_container}
END

Set Suite Variable ${kubeconfig}
Set Suite Variable ${KUBERNETES_DISTRIBUTION_BINARY}
Expand All @@ -986,6 +1002,8 @@ Suite Initialization
Set Suite Variable ${ANOMALY_THRESHOLD}
Set Suite Variable ${CONTAINER_RESTART_AGE}
Set Suite Variable ${CONTAINER_RESTART_THRESHOLD}
Set Suite Variable ${EXCLUDED_CONTAINER_NAMES}
Set Suite Variable @{EXCLUDED_CONTAINERS}
${env}= Evaluate {"KUBECONFIG":"${kubeconfig.key}","KUBERNETES_DISTRIBUTION_BINARY":"${KUBERNETES_DISTRIBUTION_BINARY}","CONTEXT":"${CONTEXT}","NAMESPACE":"${NAMESPACE}","STATEFULSET_NAME":"${STATEFULSET_NAME}","CONTAINER_RESTART_AGE":"${CONTAINER_RESTART_AGE}","CONTAINER_RESTART_THRESHOLD":"${CONTAINER_RESTART_THRESHOLD}"}
Set Suite Variable ${env}

Expand Down
6 changes: 3 additions & 3 deletions libraries/RW/CLI/CLI.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ def _create_secrets_from_kwargs(**kwargs) -> list[platform.ShellServiceRequestSe
if not key.startswith(SECRET_PREFIX) and not key.startswith(SECRET_FILE_PREFIX):
continue
if not isinstance(value, platform.Secret):
logger.warning(
logger.warn(
Comment thread
stewartshea marked this conversation as resolved.
Outdated
f"kwarg secret {value} in key {key} is the wrong type, should be platform.Secret"
)
continue
Expand Down Expand Up @@ -217,7 +217,7 @@ def _copy_files_to_staging_dir(source_dir: str, staging_dir: str) -> dict:
with open(staged_path, "w", encoding="utf-8") as out_f:
out_f.write(content)
except Exception as e:
logger.warning(f"Could not stage file '{full_path}': {e}")
logger.warn(f"Could not stage file '{full_path}': {e}")
return files_dict

def find_file(*paths):
Expand Down Expand Up @@ -326,7 +326,7 @@ def run_bash_file(
else:
# Not found directly, so do fallback logic with resolve_path_to_robot
cwd = os.getcwd()
logger.warning(f"File '{bash_file}' not found in '{cwd}'. Attempting fallback logic...")
logger.warn(f"File '{bash_file}' not found in '{cwd}'. Attempting fallback logic...")

# Might return something like "/path/to/.../sli.robot"
rw_path_to_robot = resolve_path_to_robot()
Expand Down
16 changes: 8 additions & 8 deletions libraries/RW/CLI/json_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,13 @@ def parse_cli_json_output(
try:
jmespath_result = jmespath.search(jmespath_str, json_data)
if jmespath_result == None:
logger.warning(
logger.warn(
f"The jmespath extraction string: {jmespath_str} returned None for the variable: {varname} with kwarg parts: {kwarg_parts} - did a previous extract fail?"
)
variable_results[varname] = jmespath_result
variable_from_path[varname] = jmespath_str
except Exception as e:
logger.warning(
logger.warn(
f"Failed to extract jmespath data: {json.dumps(variable_results[varname])} with path: {jmespath_str} due to: {e}"
)
variable_results[varname] = None
Expand All @@ -154,7 +154,7 @@ def parse_cli_json_output(
jmespath_str = kwargs[key]
from_varname = kwarg_parts[1]
if from_varname not in variable_results.keys():
logger.warning(
logger.warn(
f"attempted to reference from_var {from_varname} when it has not been created yet. Available vars: {variable_results.keys()}"
)
continue
Expand All @@ -167,7 +167,7 @@ def parse_cli_json_output(
variable_results[to_varname] = jmespath.search(jmespath_str, variable_results[from_varname])
variable_from_path[to_varname] = jmespath_str
except Exception as e:
logger.warning(
logger.warn(
f"Failed to extract jmespath data: {json.dumps(variable_results[from_varname])} with path: {jmespath_str} due to: {e}"
)
variable_results[to_varname] = None
Expand All @@ -181,7 +181,7 @@ def parse_cli_json_output(
varname = kwarg_parts[0]
filter_type = kwarg_parts[1]
if filter_type not in RECOGNIZED_FILTERS:
logger.warning(f"filter: {filter_type} is not in the expected types: {RECOGNIZED_FILTERS}")
logger.warn(f"filter: {filter_type} is not in the expected types: {RECOGNIZED_FILTERS}")
continue
filter_amount = kwarg_parts[2]
field_to_filter_on = kwargs[key]
Expand Down Expand Up @@ -231,7 +231,7 @@ def parse_cli_json_output(
continue
from_varname = kwargs[key]
if from_varname not in variable_results.keys():
logger.warning(
logger.warn(
f"attempted to reference from_var {from_varname} when it has not been created yet. Available vars: {variable_results.keys()}"
)
continue
Expand Down Expand Up @@ -289,7 +289,7 @@ def _check_for_json_issue(
logger.info(f"Query {query} not in recognized list: {RECOGNIZED_JSON_PARSE_QUERIES}")
continue
if prefix not in variable_results.keys():
logger.warning(
logger.warn(
f"Variable {prefix} hasn't been defined by assignment or extract, try define it in {variable_results.keys()} first"
)
continue
Expand All @@ -303,7 +303,7 @@ def _check_for_json_issue(
variable_value = float(variable_value)
numeric_castable = True
except Exception as e:
logger.warning(
logger.warn(
f"Numeric parse query requested but values not castable: {query_value} and {variable_value}"
)
# If True/False string passed from robot layer, cast it to bool
Expand Down
4 changes: 2 additions & 2 deletions libraries/RW/CLI/stdout_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def parse_cli_output_by_line(
query_parts = parse_query.split("__")
if len(query_parts) != 2:
if not squelch_further_warnings:
logger.warning(f"Could not parse query: {parse_query}")
logger.warn(f"Could not parse query: {parse_query}")
squelch_further_warnings = True
continue
prefix = query_parts[0]
Expand All @@ -192,7 +192,7 @@ def parse_cli_output_by_line(
capture_group_value = float(capture_group_value)
numeric_castable = True
except Exception as e:
logger.warning(
logger.warn(
f"Numeric parse query requested but values not castable: {query_value} and {capture_group_value}"
)
# process applicable query
Expand Down
2 changes: 1 addition & 1 deletion libraries/RW/K8sApplications/_test_parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def test_golang_report():
with open(f"{THIS_DIR}/{TEST_DATA_DIR}/golang.log", "r") as f:
data = f.read()
if len(data) > MAX_LOG_LINES:
logger.warning(
logger.warn(
f"Length of logs provided for parsing stacktraces is greater than {MAX_LOG_LINES}, be aware this could effect performance"
)
results = parse_stacktraces(
Expand Down
Loading
Loading