Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into pydantic_v2_compat
Browse files Browse the repository at this point in the history
  • Loading branch information
adamkirchberger committed Oct 30, 2023
2 parents b2b6280 + 2ba588c commit a7ecfe0
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 36 deletions.
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,36 @@



## v0.18.1 (2023-10-30)

### Fix

* fix(deps): bump cryptography from 41.0.3 to 41.0.4 (#20)

Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.3 to 41.0.4.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/41.0.3...41.0.4)

---
updated-dependencies:
- dependency-name: cryptography
dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Adam Kirchberger <[email protected]> ([`8c6d0b6`](https://github.com/adamkirchberger/nectl/commit/8c6d0b6231bfaf19a41807627c1e0537a2d540ab))


## v0.18.0 (2023-10-30)

### Feature

* feat: discovered hosts returned as dict (#25)

* feat: discovered hosts returned as dict ([`62ef067`](https://github.com/adamkirchberger/nectl/commit/62ef067ae25f23a41a34eb0556572dcd8caed6b3))


## v0.17.1 (2023-10-24)

### Fix
Expand Down
10 changes: 5 additions & 5 deletions nectl/configs/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def render_cmd(
role=role,
deployment_group=deployment_group,
)
nectl.render_configs(hosts=hosts)
nectl.render_configs(hosts=hosts.values())
except (DiscoveryError, RenderError) as e:
print(f"Error: {e}")
sys.exit(1)
Expand Down Expand Up @@ -103,7 +103,7 @@ def diff_cmd(
deployment_group=deployment_group,
)
nectl.diff_configs(
hosts=hosts,
hosts=hosts.values(),
username=username,
password=password,
ssh_private_key_file=ssh_key,
Expand Down Expand Up @@ -158,7 +158,7 @@ def apply_cmd(
)

print("Applying config to:")
print("\n".join([f"- {host.id}" for host in hosts]))
print("\n".join([f"- {host}" for host in hosts.keys()]))

if not assumeyes:
click.confirm(

Check warning on line 164 in nectl/configs/cli.py

View check run for this annotation

Codecov / codecov/patch

nectl/configs/cli.py#L164

Added line #L164 was not covered by tests
Expand All @@ -167,7 +167,7 @@ def apply_cmd(
)

nectl.apply_configs(
hosts=hosts,
hosts=hosts.values(),
username=username,
password=password,
ssh_private_key_file=ssh_key,
Expand Down Expand Up @@ -214,7 +214,7 @@ def get_cmd(
deployment_group=deployment_group,
)
nectl.get_configs(
hosts=hosts,
hosts=hosts.values(),
username=username,
password=password,
ssh_private_key_file=ssh_key,
Expand Down
8 changes: 5 additions & 3 deletions nectl/datatree/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,13 @@ def list_hosts_cmd(
sys.exit(1)

if output == "json":
print(json.dumps({h.id: h.dict() for h in hosts}, indent=4, default=str))
print(
json.dumps({h.id: h.dict() for h in hosts.values()}, indent=4, default=str)
)
else:
print(
tabulate(
[h.dict() for h in hosts],
[h.dict() for h in hosts.values()],
headers="keys",
tablefmt="psql",
)
Expand Down Expand Up @@ -118,7 +120,7 @@ def get_facts_cmd(
print(f"Error: {e}")
sys.exit(1)

host_facts = {host.id: host.facts for host in hosts}
host_facts = {host.id: host.facts for host in hosts.values()}

if not check:
print(facts_to_json_string(host_facts))
22 changes: 11 additions & 11 deletions nectl/datatree/hosts.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def get_filtered_hosts(
site: str = None,
role: str = None,
deployment_group: str = None,
) -> List[Host]:
) -> Dict[str, Host]:
"""
Returns a list of filtered hosts
Expand All @@ -178,7 +178,7 @@ def get_filtered_hosts(
deployment_group (str): filter by deployment group.
Returns:
List[Host]: list of discovered hosts.
Dict[str, Host]: discovered host instances mapped by host ID.
Raises:
DiscoveryError: if hosts cannot be successfully discovered.
Expand All @@ -205,18 +205,18 @@ def is_match(host: Host) -> bool:
return False
return True

hosts = []
hosts = {}

# Loop hosts
for host in get_all_hosts(settings=settings):
for host in get_all_hosts(settings=settings).values():
# Check for match against filters
if is_match(host):
# Add host
hosts.append(host)
hosts[host.id] = host

logger.info(
f"filter matched {len(hosts)} hosts: "
f"{','.join([host.id for host in hosts])}"
f"{','.join([host for host in hosts.keys()])}"
)

if len(hosts) == 0:
Expand Down Expand Up @@ -251,7 +251,7 @@ def _get_host_datatree_path_vars(host_path: str, datatree_dirname: str) -> dict:
]

# Extract host module import path
m = re.match(re.compile(fr".*({datatree_dirname}\/.*?)(\.py)?$"), host_path)
m = re.match(re.compile(rf".*({datatree_dirname}\/.*?)(\.py)?$"), host_path)
if m:
try:
# Import host module
Expand All @@ -269,20 +269,20 @@ def _get_host_datatree_path_vars(host_path: str, datatree_dirname: str) -> dict:
return {}


def get_all_hosts(settings: Settings) -> List[Host]:
def get_all_hosts(settings: Settings) -> Dict[str, Host]:
"""
Returns list of all discovered hosts from datatree.
Args:
settings (Settings): config settings.
Returns:
List[Host]: list of discovered hosts.
Dict[str, Host]: discovered host instances mapped by host ID.
Raises:
DiscoveryError: if hosts cannot be successfully discovered.
"""
hosts: List[Host] = []
hosts: Dict[str, Host] = {}
hostname: str = ""
site: Optional[str] = None
customer: Optional[str] = None
Expand Down Expand Up @@ -359,7 +359,7 @@ def get_all_hosts(settings: Settings) -> List[Host]:
**host_vars,
)
logger.debug(f"found host '{new_host.id}' in: {host_dir}")
hosts.append(new_host)
hosts[new_host.id] = new_host

dur = f"{time.perf_counter()-ts_start:0.4f}"
logger.info(f"finished discovery of {len(hosts)} hosts ({dur}s)")
Expand Down
8 changes: 5 additions & 3 deletions nectl/nectl.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with Nectl. If not, see <http://www.gnu.org/licenses/>.

from typing import Optional, List
from typing import Optional, List, Dict

from .logging import get_logger
from .settings import load_settings, Settings
Expand All @@ -38,15 +38,14 @@ def __init__(
"""
self.settings = settings if settings else load_settings(filepath=kit_filepath)

# TODO: return dict of hosts instead
def get_hosts(
self,
hostname: Optional[str] = None,
customer: Optional[str] = None,
site: Optional[str] = None,
role: Optional[str] = None,
deployment_group: Optional[str] = None,
) -> List[Host]:
) -> Dict[str, Host]:
"""
Get hosts from datatree that match supplied filter parameters.
Expand All @@ -57,6 +56,9 @@ def get_hosts(
role (str): optional role to filter by.
deployment_group (str): optional deployment_group to filter by.
Returns:
Dict[str, Host]: discovered host instances mapped by host ID.
Raises:
DiscoveryError: when an error has been encountered during data tree discovery.
"""
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "nectl"
version = "0.17.1"
version = "0.18.1"
description = "An end-to-end Python-based Infrastructure as Code framework for network automation and orchestration."
authors = ["Adam Kirchberger <[email protected]>"]
readme = "README.md"
Expand Down
40 changes: 27 additions & 13 deletions tests/integration/test_hosts_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ def test_should_return_8_hosts_when_getting_all_hosts(mock_settings):
# WHEN fetching all hosts
hosts = get_all_hosts(settings=settings)

# THEN expect each host to be of Host type
for host in hosts:
for host_id, host in hosts.items():
# THEN expect each host to be of Host type
assert isinstance(host, Host), host

# THEN expect host ID key
assert host_id == host.id

# THEN expect to have 8 hosts
assert len(hosts) == 8

Expand Down Expand Up @@ -99,7 +102,7 @@ def test_should_return_no_customer_when_when_getting_all_hosts_and_no_customer_r
settings.hosts_customer_regex = None

# WHEN fetching all hosts
hosts = get_all_hosts(settings=settings)
hosts = list(get_all_hosts(settings=settings).values())

# THEN expect site to be set
assert hosts[0].site is not None
Expand All @@ -119,7 +122,7 @@ def test_should_return_no_customer_and_site_when_when_getting_all_hosts_and_no_c
settings.hosts_site_regex = None

# WHEN fetching all hosts
hosts = get_all_hosts(settings=settings)
hosts = list(get_all_hosts(settings=settings).values())

# THEN expect customer to be none
assert hosts[0].customer is None
Expand All @@ -128,7 +131,7 @@ def test_should_return_no_customer_and_site_when_when_getting_all_hosts_and_no_c
assert hosts[0].customer is None


def test_should_return_empty_list_when_getting_filtered_hosts_that_dont_exist(
def test_should_return_empty_dict_when_getting_filtered_hosts_that_dont_exist(
mock_settings,
):
# GIVEN settings using mock kit
Expand All @@ -143,8 +146,8 @@ def test_should_return_empty_list_when_getting_filtered_hosts_that_dont_exist(
# WHEN fetching hosts and using filters
hosts = get_filtered_hosts(settings=settings, site=site, customer=customer)

# THEN expect result to be empty list
assert hosts == []
# THEN expect result to be empty dict
assert hosts == {}


def test_should_return_2_hosts_when_getting_filtered_hosts_by_site_and_customer(
Expand All @@ -165,10 +168,13 @@ def test_should_return_2_hosts_when_getting_filtered_hosts_by_site_and_customer(
# THEN expect to have 2 hosts
assert len(hosts) == 2

for host in hosts:
for host_id, host in hosts.items():
# THEN expect each result to be of Host type
assert isinstance(host, Host), host

# THEN expect host ID key
assert host_id == host.id

# THEN expect host customer
assert host.customer == customer

Expand All @@ -194,10 +200,13 @@ def test_should_return_2_hosts_when_getting_filtered_hosts_by_site_and_role(
# THEN expect to have 2 hosts
assert len(hosts) == 2

for host in hosts:
for host_id, host in hosts.items():
# THEN expect each result to be of Host type
assert isinstance(host, Host), host

# THEN expect host ID key
assert host_id == host.id

# THEN expect host role
assert host.role == role

Expand Down Expand Up @@ -225,10 +234,13 @@ def test_should_return_2_hosts_when_getting_filtered_hosts_by_customer_and_deplo
# THEN expect to have 2 hosts
assert len(hosts) == 2

for host in hosts:
for host_id, host in hosts.items():
# THEN expect each result to be of Host type
assert isinstance(host, Host), host

# THEN expect host ID key
assert host_id == host.id

# THEN expect host customer
assert host.customer == customer

Expand All @@ -252,8 +264,10 @@ def test_should_return_host_properties_when_getting_filtered_hosts_by_site_and_c
hostname = "core0"

# WHEN fetching hosts and using filters
hosts = get_filtered_hosts(
settings=settings, site=site, customer=customer, hostname=hostname
hosts = list(
get_filtered_hosts(
settings=settings, site=site, customer=customer, hostname=hostname
).values()
)

# THEN expect one host
Expand Down Expand Up @@ -299,7 +313,7 @@ def test_should_return_hosts_when_getting_all_hosts_that_are_not_directories(tmp
)

# WHEN fetching all hosts
hosts = get_all_hosts(settings=settings)
hosts = list(get_all_hosts(settings=settings).values())

# THEN expect total hosts
assert len(hosts) == 1
Expand Down

0 comments on commit a7ecfe0

Please sign in to comment.