Skip to content

Commit

Permalink
Deploy: replacing Target with IP,set original_host
Browse files Browse the repository at this point in the history
  • Loading branch information
Jan Gutsche committed Jan 25, 2024
1 parent 4368185 commit 6992b5a
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 80 deletions.
147 changes: 68 additions & 79 deletions scripts/deploy/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,92 +120,76 @@ def get_known_targets() -> dict[str, dict[str, str]]:
return KNOWN_TARGETS


class Target:
def __init__(self, identifier: str) -> None:
"""
Target represents a robot to deploy to.
It can be initialized with a hostname, IP address or a robot name.
"""
self.ip: Optional[ipaddress.IPv4Address | ipaddress.IPv6Address] = self._identify_ip(identifier)
self.hostname: Optional[str] = None # TODO: Get the hostname after we have a connection

def _identify_ip(self, identifier: str) -> Optional[ipaddress.IPv4Address | ipaddress.IPv6Address]:
"""
Identifies an IP address from an identifier.
The identifier can be a hostname, IP address or a robot name.
:param identifier: The identifier to identify the target from.
:return: IP address of the identified target.
"""
print_debug(f"Identifying IP address from identifier: '{identifier}'.")

# Is the identifier an IP address?
try:
print_debug(f"Checking if {identifier} is a IP address")
ip = ipaddress.ip_address(identifier)
print_debug(f"Found {ip} as IP address")
return ip
except ValueError:
print_debug("Entered target is not a IP-address.")

# It was not an IP address, so we try to find a known target
for ip, values in KNOWN_TARGETS.items():
# Is the identifier a known hostname?
known_hostname = values.get("hostname", None)
if known_hostname:
print_debug(f"Comparing {identifier} with {known_hostname}")
if known_hostname.strip() == identifier.strip():
print_debug(f"Found hostname '{known_hostname}' for identifier '{identifier}'. Using its IP {ip}.")
return ipaddress.ip_address(ip)
else:
print_debug(f"Hostname '{known_hostname}' does not match identifier '{identifier}'.")

# Is the identifier a known robot name?
known_robot_name = values.get("robot_name", None)
if known_robot_name:
print_debug(f"Comparing '{identifier}' with '{known_robot_name}'.")
if known_robot_name.strip() == identifier.strip():
print_debug(
f"Found robot name '{known_robot_name}' for identifier '{identifier}'. Using its IP {ip}."
)
return ipaddress.ip_address(ip)
else:
print_debug(f"Robot name '{known_robot_name}' does not match identifier '{identifier}'.")

def __str__(self) -> str:
"""Returns the target's hostname if available or IP address."""
return self.hostname if self.hostname is not None else str(self.ip)

def get_connection_identifier(self) -> str:
"""Returns the target's IP address."""
return str(self.ip)


def _parse_targets(input_targets: str) -> list[Target]:
def _identify_ip(identifier: str) -> str | None:
"""
Identifies an IP address from an identifier.
The identifier can be a hostname, IP address or a robot name.
:param identifier: The identifier to identify the target from.
:return: IP address of the identified target.
"""
print_debug(f"Identifying IP address from identifier: '{identifier}'.")

# Is the identifier an IP address?
try:
print_debug(f"Checking if {identifier} is an IP address")
ip = ipaddress.ip_address(identifier)
print_debug(f"Identified {ip} as an IP address")
return str(ip)
except ValueError:
print_debug("Entered target is not an IP-address.")

# It was not an IP address, so we try to find a known target
for ip, values in KNOWN_TARGETS.items():
# Is the identifier a known hostname?
known_hostname = values.get("hostname", None)
if known_hostname:
print_debug(f"Comparing {identifier} with {known_hostname}")
if known_hostname.strip() == identifier.strip():
print_debug(f"Identified hostname '{known_hostname}' for '{identifier}'. Using its IP {ip}.")
return str(ipaddress.ip_address(ip))
else:
print_debug(f"Hostname '{known_hostname}' does not match identifier '{identifier}'.")

# Is the identifier a known robot name?
known_robot_name = values.get("robot_name", None)
if known_robot_name:
print_debug(f"Comparing '{identifier}' with '{known_robot_name}'.")
if known_robot_name.strip() == identifier.strip():
print_debug(f"Identified robot name '{known_robot_name}' for '{identifier}'. Using its IP {ip}.")
return str(ipaddress.ip_address(ip))
else:
print_debug(f"Robot name '{known_robot_name}' does not match '{identifier}'.")


def _parse_targets(input_targets: str) -> list[str]:
"""
Parse target input into usable Targets.
Parse target input into usable target IP addresses.
:param input_targets: The input string of targets as a comma separated string of either hostnames, robot names or IPs.
:return: List of Targets
:return: List of target IP addresses.
"""
targets: list[Target] = []
target_ips: list[str] = []
for input_target in input_targets.split(","):
try:
target = Target(input_target)
target_ip = _identify_ip(input_target)
except ValueError:
print_err(f"Could not determine hostname or IP from input: '{input_target}'")
print_err(f"Could not determine IP address from input: '{input_target}'")
exit(1)
if target_ip is None:
print_err(f"Could not determine IP address from input:' {input_target}'")
exit(1)
targets.append(target)
return targets
target_ips.append(target_ip)
return target_ips


def _get_connections_from_targets(
targets: list[Target], user: str, connection_timeout: Optional[int] = 10
target_ips: list[str], user: str, connection_timeout: Optional[int] = 10
) -> ThreadingGroup:
"""
Get connections to the given Targets using the given username.
Get connections to the given target IP addresses using the given username.
:param targets: The Targets to connect to
:param target_ips: The target IP addresses to connect to
:param user: The username to connect with
:param connection_timeout: Timeout for establishing the connection
:return: The connections
Expand All @@ -219,14 +203,17 @@ def _concat_exception_args(e: Exception) -> str:
reason += f"{arg} "
return reason

hosts: list[str] = [target.get_connection_identifier() for target in targets]
connections = ThreadingGroup(*hosts, user=user, connect_timeout=connection_timeout)
connections = ThreadingGroup(*target_ips, user=user, connect_timeout=connection_timeout)
failures: list[tuple[Connection, str]] = [] # List of tuples of failed connections and their error message
for connection in connections:
try:
print_debug(f"Connecting to {connection.host}...")
connection.open()
print_debug(f"Connected to {connection.host}...")
print_debug(f"Getting hostname of {connection.host}...")
hostname: str = connection.run("hostname", hide=hide_output()).stdout.strip()
print_debug(f"Got hostname of {connection.host}: {hostname}. Setting is as original hostname.")
connection.original_host = hostname
except AuthenticationException as e:
failures.append(
(
Expand Down Expand Up @@ -257,11 +244,13 @@ def _get_connections_from_all_known_targets(user: str, connection_timeout: Optio
:param connection_timeout: Timeout for establishing the connection
:return: The connections
"""
# Get hosts from all known targets
hosts: list[str] = [Target(hostname).get_connection_identifier() for hostname in KNOWN_TARGETS.keys()]
# Get all known target IP addresses
target_ips: list[str] = list(KNOWN_TARGETS.keys())

# Create connections
connections: list[Connection] = [Connection(host, user=user, connect_timeout=connection_timeout) for host in hosts]
connections: list[Connection] = [
Connection(host, user=user, connect_timeout=connection_timeout) for host in target_ips
]

# Connect to all hosts
open_connections: list[Connection] = []
Expand Down Expand Up @@ -293,11 +282,11 @@ def get_connections_from_targets(
:return: The connections to the targets
"""
if input_targets == "ALL":
print_info(f"Connecting to all known Targets: {KNOWN_TARGETS.keys()}")
print_info(f"Connecting to all known targets: {KNOWN_TARGETS.keys()}")
return _get_connections_from_all_known_targets(user=user, connection_timeout=connection_timeout)

return _get_connections_from_targets(
targets=_parse_targets(input_targets), user=user, connection_timeout=connection_timeout
target_ips=_parse_targets(input_targets), user=user, connection_timeout=connection_timeout
)


Expand Down
2 changes: 1 addition & 1 deletion scripts/deploy/tasks/abstract_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def _results_hosts(self, results) -> list[str]:
:param results: The results of the task.
:return: The list of hosts that have results.
"""
return [connection.host for connection in results.keys()]
return [connection.original_host for connection in results.keys()]

def _succeeded_hosts(self, results: GroupResult) -> list[str]:
"""
Expand Down

0 comments on commit 6992b5a

Please sign in to comment.