feat: add Go file compilation and enhance network interface display functionality
This commit is contained in:
parent
4aee9266d5
commit
f0159bdea7
@ -21,4 +21,12 @@
|
|||||||
dest: "{{ ansible_env.HOME }}/.local/bin/{{ item.path | basename }}"
|
dest: "{{ ansible_env.HOME }}/.local/bin/{{ item.path | basename }}"
|
||||||
state: link
|
state: link
|
||||||
loop: "{{ utils_files.files }}"
|
loop: "{{ utils_files.files }}"
|
||||||
|
when: item.path | regex_search('\.go$') is not defined
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Compile Go files and place binaries in ~/.local/bin
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: go build -o "{{ ansible_env.HOME }}/.local/bin/{{ item.path | basename | regex_replace('\.go$', '') }}" "{{ item.path }}"
|
||||||
|
loop: "{{ utils_files.files }}"
|
||||||
|
when: item.path | regex_search('\.go$')
|
||||||
become: false
|
become: false
|
||||||
|
7
config/ansible/tasks/global/utils/helloworld.go
Normal file
7
config/ansible/tasks/global/utils/helloworld.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("Hello, World!")
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import argparse
|
import argparse
|
||||||
|
import requests
|
||||||
|
|
||||||
def get_physical_interfaces():
|
def get_physical_interfaces():
|
||||||
"""
|
"""
|
||||||
@ -50,57 +51,140 @@ def get_virtual_interfaces():
|
|||||||
|
|
||||||
return virtual_interfaces
|
return virtual_interfaces
|
||||||
|
|
||||||
def display_interface_details(show_all=False):
|
def get_up_interfaces(interfaces):
|
||||||
"""
|
"""
|
||||||
Display details of network interfaces, including their IP address, subnet mask,
|
Filters the given list of interfaces to include only those that are up or unknown.
|
||||||
and MAC address, in a formatted table.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
show_all (bool): If True, includes both physical and virtual interfaces
|
interfaces (list): A list of interface names.
|
||||||
in the output. Defaults to False, which only displays
|
|
||||||
physical interfaces.
|
|
||||||
|
|
||||||
Output:
|
Returns:
|
||||||
Prints a table with the following columns:
|
list: A list of interface names that are up or treated as up (e.g., UNKNOWN).
|
||||||
- Interface: The name of the network interface.
|
"""
|
||||||
- IP Address: The IP address assigned to the interface.
|
up_interfaces = []
|
||||||
- Subnet: The subnet mask associated with the IP address.
|
for interface in interfaces:
|
||||||
- MAC Address: The MAC address of the interface.
|
try:
|
||||||
|
result = subprocess.run(['ip', 'link', 'show', interface],
|
||||||
|
capture_output=True, text=True, check=True)
|
||||||
|
if "state UP" in result.stdout or "state UNKNOWN" in result.stdout:
|
||||||
|
up_interfaces.append(interface)
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
return up_interfaces
|
||||||
|
|
||||||
|
def get_interface_state(interface):
|
||||||
|
"""
|
||||||
|
Retrieve the state and MAC address of a network interface.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
interface (str): The name of the network interface.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: A tuple containing the state (str) and MAC address (str) of the interface.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
result = subprocess.run(['ip', 'link', 'show', interface],
|
||||||
|
capture_output=True, text=True, check=True)
|
||||||
|
lines = result.stdout.splitlines()
|
||||||
|
state = "UNKNOWN"
|
||||||
|
mac = "N/A"
|
||||||
|
|
||||||
|
if len(lines) > 0:
|
||||||
|
if "state UP" in lines[0]:
|
||||||
|
state = "UP"
|
||||||
|
elif "state DOWN" in lines[0]:
|
||||||
|
state = "DOWN"
|
||||||
|
elif "state UNKNOWN" in lines[0]:
|
||||||
|
state = "UP" # Treat UNKNOWN as UP
|
||||||
|
|
||||||
|
if len(lines) > 1:
|
||||||
|
mac = lines[1].strip().split()[1] if len(lines[1].strip().split()) > 1 else "N/A"
|
||||||
|
|
||||||
|
return state, mac
|
||||||
|
except Exception:
|
||||||
|
return "UNKNOWN", "N/A"
|
||||||
|
|
||||||
|
def get_external_ip():
|
||||||
|
"""
|
||||||
|
Fetch the external IP address of the machine.
|
||||||
|
|
||||||
|
This function attempts to retrieve the external IP address using the services
|
||||||
|
`https://ifconfig.co`, `https://ifconfig.io`, and `https://ifconfig.me`. Each
|
||||||
|
request has a timeout of 200ms to ensure speed. The user agent is explicitly
|
||||||
|
set to `curl` to ensure proper response formatting.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The external IP address if successful, or an error message if all services fail.
|
||||||
|
"""
|
||||||
|
services = ["https://ifconfig.co", "https://ifconfig.io", "https://ifconfig.me"]
|
||||||
|
headers = {"User-Agent": "curl"}
|
||||||
|
for service in services:
|
||||||
|
try:
|
||||||
|
response = requests.get(service, headers=headers, timeout=0.2)
|
||||||
|
if response.status_code == 200:
|
||||||
|
return response.text.strip()
|
||||||
|
except requests.RequestException:
|
||||||
|
continue
|
||||||
|
return "Unable to fetch external IP"
|
||||||
|
|
||||||
|
def display_interface_details(show_physical=False, show_virtual=False, show_all=False, show_external_ip=False):
|
||||||
|
"""
|
||||||
|
Display details of network interfaces based on the specified flags.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
show_physical (bool): Show physical interfaces (UP by default unless combined with show_all).
|
||||||
|
show_virtual (bool): Show virtual interfaces (UP by default unless combined with show_all).
|
||||||
|
show_all (bool): Include all interfaces (UP, DOWN, UNKNOWN).
|
||||||
|
show_external_ip (bool): Fetch and display the external IP address.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
- The function uses the `ip` command to fetch interface details.
|
- If no flags are specified, both UP physical and virtual interfaces are shown by default.
|
||||||
- If an interface does not have an IP address, "No IP" is displayed in the
|
- If `-a` is specified, it includes all physical interfaces by default.
|
||||||
IP Address column.
|
- If `-a` and `-v` are combined, it includes all physical and virtual interfaces.
|
||||||
- If an error occurs while fetching details for an interface, an error
|
- If `-e` is specified, the external IP address is displayed.
|
||||||
message is printed for that interface.
|
|
||||||
"""
|
"""
|
||||||
interfaces = get_physical_interfaces()
|
if show_external_ip:
|
||||||
|
external_ip = get_external_ip()
|
||||||
|
print(f"External IP: {external_ip}")
|
||||||
|
print("-" * 50)
|
||||||
|
|
||||||
|
interfaces = []
|
||||||
|
|
||||||
if show_all:
|
if show_all:
|
||||||
interfaces.extend(get_virtual_interfaces())
|
if show_physical or not show_virtual: # Default to physical if no `-v`
|
||||||
interfaces.sort()
|
interfaces.extend(get_physical_interfaces())
|
||||||
|
if show_virtual:
|
||||||
|
interfaces.extend(get_virtual_interfaces())
|
||||||
|
else:
|
||||||
|
if show_physical or not show_virtual: # Default to physical if no `-v`
|
||||||
|
interfaces.extend(get_up_interfaces(get_physical_interfaces()))
|
||||||
|
if show_virtual or not show_physical: # Default to virtual if no `-p`
|
||||||
|
interfaces.extend(get_up_interfaces(get_virtual_interfaces()))
|
||||||
|
|
||||||
|
interfaces.sort()
|
||||||
|
|
||||||
# Define column widths based on expected maximum content length
|
# Define column widths based on expected maximum content length
|
||||||
col_widths = {
|
col_widths = {
|
||||||
'interface': 15, # Increased to accommodate longer interface names
|
'interface': 15,
|
||||||
'ip': 18, # Increased for longer IP addresses
|
'ip': 18,
|
||||||
'subnet': 10,
|
'subnet': 10,
|
||||||
|
'state': 10,
|
||||||
'mac': 18
|
'mac': 18
|
||||||
}
|
}
|
||||||
|
|
||||||
# Print header with proper formatting
|
# Print header with proper formatting
|
||||||
print(f"{'Interface':<{col_widths['interface']}} {'IP Address':<{col_widths['ip']}} {'Subnet':<{col_widths['subnet']}} {'MAC Address':<{col_widths['mac']}}")
|
print(f"{'Interface':<{col_widths['interface']}} {'IP Address':<{col_widths['ip']}} {'Subnet':<{col_widths['subnet']}} {'State':<{col_widths['state']}} {'MAC Address':<{col_widths['mac']}}")
|
||||||
print("-" * (col_widths['interface'] + col_widths['ip'] + col_widths['subnet'] + col_widths['mac']))
|
print("-" * (col_widths['interface'] + col_widths['ip'] + col_widths['subnet'] + col_widths['state'] + col_widths['mac']))
|
||||||
|
|
||||||
for interface in interfaces:
|
for interface in interfaces:
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(['ip', '-br', 'addr', 'show', interface],
|
result = subprocess.run(['ip', '-br', 'addr', 'show', interface],
|
||||||
capture_output=True, text=True, check=True)
|
capture_output=True, text=True, check=True)
|
||||||
|
state, mac = get_interface_state(interface)
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
parts = result.stdout.strip().split()
|
parts = result.stdout.strip().split()
|
||||||
if len(parts) >= 3:
|
if len(parts) >= 3:
|
||||||
name = parts[0]
|
name = parts[0]
|
||||||
mac = parts[1]
|
|
||||||
ip_with_mask = parts[2]
|
ip_with_mask = parts[2]
|
||||||
|
|
||||||
# Split IP/mask
|
# Split IP/mask
|
||||||
@ -111,14 +195,22 @@ def display_interface_details(show_all=False):
|
|||||||
ip = ip_with_mask
|
ip = ip_with_mask
|
||||||
subnet = ""
|
subnet = ""
|
||||||
|
|
||||||
print(f"{name:<{col_widths['interface']}} {ip:<{col_widths['ip']}} {subnet:<{col_widths['subnet']}} {mac:<{col_widths['mac']}}")
|
print(f"{name:<{col_widths['interface']}} {ip:<{col_widths['ip']}} {subnet:<{col_widths['subnet']}} {state:<{col_widths['state']}} {mac:<{col_widths['mac']}}")
|
||||||
else:
|
else:
|
||||||
print(f"{interface:<{col_widths['interface']}} {'No IP':<{col_widths['ip']}} {'':<{col_widths['subnet']}} {parts[1] if len(parts) > 1 else 'N/A':<{col_widths['mac']}}")
|
print(f"{interface:<{col_widths['interface']}} {'No IP':<{col_widths['ip']}} {'':<{col_widths['subnet']}} {state:<{col_widths['state']}} {mac:<{col_widths['mac']}}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error fetching details for {interface}: {e}")
|
print(f"Error fetching details for {interface}: {e}")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser(description='Display network interface information')
|
parser = argparse.ArgumentParser(description='Display network interface information')
|
||||||
parser.add_argument('-a', '--all', action='store_true', help='Show all interfaces including virtual ones like Tailscale and WireGuard')
|
parser.add_argument('-p', action='store_true', help='Show physical interfaces (UP by default)')
|
||||||
|
parser.add_argument('-v', action='store_true', help='Show virtual interfaces (UP by default)')
|
||||||
|
parser.add_argument('-a', action='store_true', help='Include all interfaces (UP, DOWN, UNKNOWN)')
|
||||||
|
parser.add_argument('-e', action='store_true', help='Fetch and display the external IP address')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
display_interface_details(args.all)
|
|
||||||
|
# Default to showing both UP physical and virtual interfaces if no flags are specified
|
||||||
|
display_interface_details(show_physical=args.p or not (args.p or args.v or args.a or args.e),
|
||||||
|
show_virtual=args.v or not (args.p or args.v or args.a or args.e),
|
||||||
|
show_all=args.a,
|
||||||
|
show_external_ip=args.e)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user