Skip to content

Commit

Permalink
raise if __exit__ fail (#2294)
Browse files Browse the repository at this point in the history
* raise if __exit__ fail

* Add tests for resource context manager
  • Loading branch information
myakove authored Jan 27, 2025
1 parent 0318516 commit 5081fcf
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 23 deletions.
8 changes: 8 additions & 0 deletions ocp_resources/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,11 @@ def __str__(self):

class NNCPConfigurationFailed(Exception):
pass


class ResourceTeardownError(Exception):
def __init__(self, resource: Any):
self.resource = resource

def __str__(self):
return f"Failed to excute teardown for resource {self.resource}"
43 changes: 22 additions & 21 deletions ocp_resources/resource.py
Original file line number Diff line number Diff line change
@@ -1,58 +1,55 @@
from __future__ import annotations

from collections.abc import Callable, Generator
import contextlib

import copy
import json
from warnings import warn

import os
import re
import sys
from collections.abc import Callable, Generator
from io import StringIO
from signal import SIGINT, signal
from types import TracebackType
from typing import Any
from warnings import warn

import kubernetes
from kubernetes.dynamic import DynamicClient, ResourceInstance
import yaml
from benedict import benedict
from kubernetes.dynamic import DynamicClient, ResourceInstance
from kubernetes.dynamic.exceptions import (
ConflictError,
ForbiddenError,
MethodNotAllowedError,
NotFoundError,
ForbiddenError,
ResourceNotFoundError,
)
from kubernetes.dynamic.resource import ResourceField
from packaging.version import Version
from simple_logger.logger import get_logger, logging
from timeout_sampler import (
TimeoutExpiredError,
TimeoutSampler,
TimeoutWatch,
)
from urllib3.exceptions import MaxRetryError

from ocp_resources.event import Event
from ocp_resources.exceptions import MissingRequiredArgumentError, MissingResourceResError, ResourceTeardownError
from ocp_resources.utils.constants import (
DEFAULT_CLUSTER_RETRY_EXCEPTIONS,
NOT_FOUND_ERROR_EXCEPTION_DICT,
PROTOCOL_ERROR_EXCEPTION_DICT,
TIMEOUT_1MINUTE,
TIMEOUT_1SEC,
TIMEOUT_4MINUTES,
TIMEOUT_5SEC,
TIMEOUT_10SEC,
TIMEOUT_30SEC,
TIMEOUT_5SEC,
TIMEOUT_1SEC,
)
from ocp_resources.event import Event
from timeout_sampler import (
TimeoutExpiredError,
TimeoutSampler,
TimeoutWatch,
)
from ocp_resources.exceptions import MissingRequiredArgumentError, MissingResourceResError
from ocp_resources.utils.resource_constants import ResourceConstants
from ocp_resources.utils.utils import skip_existing_resource_creation_teardown


LOGGER = get_logger(name=__name__)
MAX_SUPPORTED_API_VERSION = "v2"

Expand Down Expand Up @@ -571,7 +568,8 @@ def __exit__(
exc_tb: TracebackType | None = None,
) -> None:
if self.teardown:
self.clean_up()
if not self.clean_up():
raise ResourceTeardownError(resource=self)

def _sigint_handler(self, signal_received: int, frame: Any) -> None:
self.__exit__()
Expand Down Expand Up @@ -745,10 +743,13 @@ def wait_deleted(self, timeout: int = TIMEOUT_4MINUTES) -> bool:
TimeoutExpiredError: If resource still exists.
"""
self.logger.info(f"Wait until {self.kind} {self.name} is deleted")
samples = TimeoutSampler(wait_timeout=timeout, sleep=1, func=lambda: self.exists)
for sample in samples:
if not sample:
return True
try:
for sample in TimeoutSampler(wait_timeout=timeout, sleep=1, func=lambda: self.exists):
if not sample:
return True
except TimeoutExpiredError:
self.logger.warning(f"Timeout expired while waiting for {self.kind} {self.name} to be deleted")
return False

return False

Expand Down
25 changes: 23 additions & 2 deletions tests/test_resources.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import pytest
import yaml
from testcontainers.k3s import K3SContainer

from ocp_resources.exceptions import ResourceTeardownError
from ocp_resources.namespace import Namespace
from ocp_resources.pod import Pod
from ocp_resources.resource import Resource, get_client
import yaml
from testcontainers.k3s import K3SContainer
from ocp_resources.secret import Secret


class TestSecretExit(Secret):
def deploy(self, wait: bool = False):
return self

def clean_up(self, wait: bool = True, timeout: int | None = None) -> bool:
return False


@pytest.fixture(scope="session")
Expand Down Expand Up @@ -82,3 +92,14 @@ def test_update_replace(self, namespace):

def test_cleanup(self, namespace):
namespace.clean_up(wait=False)

def test_resource_context_manager(self, client):
with Secret(name="test-context-manager", namespace="default", client=client) as sec:
pass

assert not sec.exists

def test_resource_context_manager_exit(self, client):
with pytest.raises(ResourceTeardownError):
with TestSecretExit(name="test-context-manager-exit", namespace="default", client=client):
pass

0 comments on commit 5081fcf

Please sign in to comment.