Skip to content

Commit

Permalink
Use dataclass for Instance
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardobranco777 committed Feb 25, 2024
1 parent 7c0f52f commit 0e5b3ae
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 35 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ flake8:

.PHONY: pylint
pylint:
@pylint $(FILES)
@pylint --disable=duplicate-code $(FILES)

.PHONY: test
test:
Expand Down
1 change: 1 addition & 0 deletions cloudview/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
cloudview
"""

__author__ = """Ricardo Branco"""
__email__ = "rbranco@suse.de"
__version__ = "0.9.7"
9 changes: 3 additions & 6 deletions cloudview/cloudview.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,7 @@ def get_clients(
providers = (
(provider,)
if provider
else config["providers"].keys()
if config
else PROVIDERS.keys()
else config["providers"].keys() if config else PROVIDERS.keys()
)
clients = []
for xprovider in providers:
Expand All @@ -66,9 +64,7 @@ def get_clients(
clouds = (
(cloud,)
if cloud
else config["providers"][xprovider].keys()
if config
else ("",)
else config["providers"][xprovider].keys() if config else ("",)
)
for xcloud in clouds:
try:
Expand Down Expand Up @@ -100,6 +96,7 @@ def print_instances(client: CSP) -> None:
params = urlencode(instance.params)
resource = "/".join([instance.provider.lower(), f"{instance.id}?{params}"])
instance.href = f"instance/{resource}"
assert not isinstance(instance.time, str)
instance.time = dateit(instance.time, args.time)
Output().info(instance)

Expand Down
2 changes: 1 addition & 1 deletion cloudview/ec2.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def _node_to_instance(self, node: Node, region: str) -> Instance:
provider=Provider.EC2,
cloud=self.cloud,
name=node.extra["tags"].get("Name", node.name),
id=node.id,
id=str(node.id),
size=node.extra["instance_type"],
time=utc_date(node.extra["launch_time"]),
state=node.state,
Expand Down
2 changes: 1 addition & 1 deletion cloudview/gce.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def _node_to_instance(self, node: Node) -> Instance:
provider=Provider.GCE,
cloud=self.cloud,
name=node.name,
id=node.id,
id=str(node.id),
size=node.extra["machineType"].split("/")[-1],
time=utc_date(node.extra["creationTimestamp"]),
state=node.state,
Expand Down
22 changes: 14 additions & 8 deletions cloudview/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"""

import logging
from dataclasses import dataclass
from datetime import datetime
from typing import Any

from cachetools import cached, TTLCache
Expand All @@ -15,18 +17,22 @@
STATES = [str(getattr(NodeState, _)) for _ in dir(NodeState) if _.isupper()]


class Instance:
@dataclass(kw_only=True)
class Instance: # pylint: disable=too-many-instance-attributes
"""
Instance class
"""

def __init__(self, **kwargs):
for attr, value in kwargs.items():
setattr(self, attr, value)

def __repr__(self) -> str:
attrs = ", ".join(f"{attr}={getattr(self, attr)!r}" for attr in vars(self))
return f"{self.__class__.__name__}({attrs})"
provider: str
cloud: str
name: str
id: str
size: str
time: str | datetime
state: str
location: str
extra: dict
params: dict

# Allow access this object as a dictionary

Expand Down
2 changes: 1 addition & 1 deletion cloudview/openstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def _node_to_instance(self, node: Node) -> Instance:
provider=Provider.OPENSTACK,
cloud=self.cloud,
name=node.name,
id=node.id,
id=str(node.id),
size=self._get_size(node.extra["flavorId"]),
time=utc_date(node.extra["created"]),
state=node.state,
Expand Down
5 changes: 5 additions & 0 deletions tests/test_ec2.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ def mock_ec2_instance():
"availability": "us-east-1a",
"tags": {"Name": "test-instance"},
},
provider="Provider",
cloud="Cloud",
time="2023-04-19T13:04:22.000Z",
location="Location",
params={},
)


Expand Down
112 changes: 96 additions & 16 deletions tests/test_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,90 @@


def test_instance_repr():
item = Instance(name="Example", value=42, none=None, map={1: "2"})
item = Instance(
name="Example",
provider="P",
cloud="C",
id="id",
size="s",
time="T",
state="Running",
location="L",
extra={},
params={},
)
repr_string = repr(item)
recreated_item = eval(repr_string)
assert item.__dict__ == recreated_item.__dict__


def test_instance_creation():
instance = Instance(name="Example", type="VM", status="Running")
instance = Instance(
name="Example",
provider="P",
cloud="C",
id="id",
size="s",
time="T",
state="Running",
location="L",
extra={},
params={},
)
assert instance.name == "Example"
assert instance.type == "VM"
assert instance.status == "Running"
assert instance.state == "Running"


def test_instance_dict_access():
instance = Instance(name="Example", type="VM", status="Running")
instance = Instance(
name="Example",
provider="P",
cloud="C",
id="id",
size="s",
time="T",
state="Running",
location="L",
extra={},
params={},
)

assert instance["name"] == "Example"
assert instance["type"] == "VM"
assert instance["status"] == "Running"
assert instance["state"] == "Running"


def test_instance_dict_assignment():
instance = Instance()
instance = Instance(
name="name",
provider="P",
cloud="C",
id="id",
size="s",
time="T",
state="S",
location="L",
extra={},
params={},
)

instance["name"] = "Updated Name"
instance["type"] = "Updated Type"

assert instance.name == "Updated Name"
assert instance.type == "Updated Type"


def test_instance_dict_deletion():
instance = Instance(name="Alice", age=30)
instance = Instance(
name="name",
provider="P",
cloud="C",
id="id",
size="s",
time="T",
state="S",
location="L",
extra={},
params={},
)

with pytest.raises(KeyError):
del instance["nonexistent"]
Expand All @@ -50,7 +101,18 @@ def test_instance_dict_deletion():


def test_instance_unknown_attribute():
instance = Instance()
instance = Instance(
name="name",
provider="P",
cloud="C",
id="id",
size="s",
time="T",
state="S",
location="L",
extra={},
params={},
)
with pytest.raises(AttributeError):
_ = instance.unknown_attribute

Expand All @@ -61,25 +123,43 @@ def _get_instances(self):
return [
Instance(
id="id1",
instance_id="id1",
name="Instance1",
extra={"status": "running"},
provider="P",
cloud="C",
size="s",
time="T",
state="S",
location="L",
params={},
),
Instance(
id="id2",
instance_id="id2",
name="Instance2",
extra={"status": "stopped"},
provider="P",
cloud="C",
size="s",
time="T",
state="S",
location="L",
params={},
),
]

def _get_instance(self, instance_id, params):
if instance_id == "id1":
return Instance(
id="id1",
instance_id="id1",
name="Instance1",
extra={"name=": "Instance1"},
provider="P",
cloud="C",
size="s",
time="T",
state="S",
location="L",
params={},
)
return None

Expand All @@ -94,7 +174,7 @@ def test_csp_get_instances():
instances = csp.get_instances()
assert len(instances) == 2
assert instances[0].name == "Instance1"
assert instances[1].instance_id == "id2"
assert instances[1].id == "id2"


def test_csp_get_instance():
Expand Down
13 changes: 12 additions & 1 deletion tests/test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,18 @@ def test_json_output_dict(json_output, capsys):

def test_json_output_obj(json_output, capsys):
json_output.header()
info = Instance(name="instance-1", age="30")
info = Instance(
name="instance-1",
provider="P",
cloud="C",
id="id",
size="s",
time="T",
state="S",
location="L",
extra={},
params={},
)
json_output.info(info)
json_output.footer()
captured = capsys.readouterr()
Expand Down

0 comments on commit 0e5b3ae

Please sign in to comment.