feat: add utility tasks for making custom utilities available in ~/.local/bin
This commit is contained in:
parent
83358a5e22
commit
4aee9266d5
@ -27,6 +27,10 @@
|
|||||||
ansible.builtin.import_tasks: tasks/global/openssh-server.yml
|
ansible.builtin.import_tasks: tasks/global/openssh-server.yml
|
||||||
become: true
|
become: true
|
||||||
|
|
||||||
|
- name: Include Utils tasks
|
||||||
|
ansible.builtin.import_tasks: tasks/global/utils.yml
|
||||||
|
become: true
|
||||||
|
|
||||||
- name: Ensure common packages are installed
|
- name: Ensure common packages are installed
|
||||||
ansible.builtin.package:
|
ansible.builtin.package:
|
||||||
name:
|
name:
|
||||||
|
24
config/ansible/tasks/global/utils.yml
Normal file
24
config/ansible/tasks/global/utils.yml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
- name: Load DOTFILES_PATH environment variable
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
dotfiles_path: "{{ lookup('env', 'DOTFILES_PATH') }}"
|
||||||
|
|
||||||
|
- name: Ensure ~/.local/bin exists
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ ansible_env.HOME }}/.local/bin"
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Scan utils folder and create symlinks in ~/.local/bin
|
||||||
|
ansible.builtin.find:
|
||||||
|
paths: "{{ dotfiles_path }}/config/ansible/tasks/global/utils"
|
||||||
|
file_type: file
|
||||||
|
register: utils_files
|
||||||
|
|
||||||
|
- name: Create symlinks for utils scripts
|
||||||
|
ansible.builtin.file:
|
||||||
|
src: "{{ item.path }}"
|
||||||
|
dest: "{{ ansible_env.HOME }}/.local/bin/{{ item.path | basename }}"
|
||||||
|
state: link
|
||||||
|
loop: "{{ utils_files.files }}"
|
||||||
|
become: false
|
124
config/ansible/tasks/global/utils/ipaddr
Executable file
124
config/ansible/tasks/global/utils/ipaddr
Executable file
@ -0,0 +1,124 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
def get_physical_interfaces():
|
||||||
|
"""
|
||||||
|
Retrieve a list of physical network interfaces on the system.
|
||||||
|
|
||||||
|
This function checks the `/sys/class/net/` directory to identify physical
|
||||||
|
network interfaces. It determines if an interface is physical by verifying
|
||||||
|
the presence of a symbolic link to a `device` directory.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: A list of strings, where each string is the name of a physical
|
||||||
|
network interface.
|
||||||
|
"""
|
||||||
|
interfaces_path = '/sys/class/net/'
|
||||||
|
physical_interfaces = []
|
||||||
|
|
||||||
|
for interface in os.listdir(interfaces_path):
|
||||||
|
if not os.path.islink(os.path.join(interfaces_path, interface, 'device')):
|
||||||
|
continue
|
||||||
|
physical_interfaces.append(interface)
|
||||||
|
|
||||||
|
return physical_interfaces
|
||||||
|
|
||||||
|
def get_virtual_interfaces():
|
||||||
|
"""
|
||||||
|
Retrieves a list of virtual network interfaces on the system.
|
||||||
|
|
||||||
|
This function scans the network interfaces available in the '/sys/class/net/'
|
||||||
|
directory and filters out physical interfaces and the loopback interface ('lo').
|
||||||
|
It identifies virtual interfaces by checking if the 'device' path is not a
|
||||||
|
symbolic link.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: A list of virtual network interface names as strings.
|
||||||
|
"""
|
||||||
|
interfaces_path = '/sys/class/net/'
|
||||||
|
virtual_interfaces = []
|
||||||
|
|
||||||
|
for interface in os.listdir(interfaces_path):
|
||||||
|
if os.path.islink(os.path.join(interfaces_path, interface, 'device')):
|
||||||
|
continue
|
||||||
|
if interface == 'lo':
|
||||||
|
continue
|
||||||
|
virtual_interfaces.append(interface)
|
||||||
|
|
||||||
|
return virtual_interfaces
|
||||||
|
|
||||||
|
def display_interface_details(show_all=False):
|
||||||
|
"""
|
||||||
|
Display details of network interfaces, including their IP address, subnet mask,
|
||||||
|
and MAC address, in a formatted table.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
show_all (bool): If True, includes both physical and virtual interfaces
|
||||||
|
in the output. Defaults to False, which only displays
|
||||||
|
physical interfaces.
|
||||||
|
|
||||||
|
Output:
|
||||||
|
Prints a table with the following columns:
|
||||||
|
- Interface: The name of the network interface.
|
||||||
|
- IP Address: The IP address assigned to the interface.
|
||||||
|
- Subnet: The subnet mask associated with the IP address.
|
||||||
|
- MAC Address: The MAC address of the interface.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- The function uses the `ip` command to fetch interface details.
|
||||||
|
- If an interface does not have an IP address, "No IP" is displayed in the
|
||||||
|
IP Address column.
|
||||||
|
- If an error occurs while fetching details for an interface, an error
|
||||||
|
message is printed for that interface.
|
||||||
|
"""
|
||||||
|
interfaces = get_physical_interfaces()
|
||||||
|
|
||||||
|
if show_all:
|
||||||
|
interfaces.extend(get_virtual_interfaces())
|
||||||
|
interfaces.sort()
|
||||||
|
|
||||||
|
# Define column widths based on expected maximum content length
|
||||||
|
col_widths = {
|
||||||
|
'interface': 15, # Increased to accommodate longer interface names
|
||||||
|
'ip': 18, # Increased for longer IP addresses
|
||||||
|
'subnet': 10,
|
||||||
|
'mac': 18
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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("-" * (col_widths['interface'] + col_widths['ip'] + col_widths['subnet'] + col_widths['mac']))
|
||||||
|
|
||||||
|
for interface in interfaces:
|
||||||
|
try:
|
||||||
|
result = subprocess.run(['ip', '-br', 'addr', 'show', interface],
|
||||||
|
capture_output=True, text=True, check=True)
|
||||||
|
if result.returncode == 0:
|
||||||
|
parts = result.stdout.strip().split()
|
||||||
|
if len(parts) >= 3:
|
||||||
|
name = parts[0]
|
||||||
|
mac = parts[1]
|
||||||
|
ip_with_mask = parts[2]
|
||||||
|
|
||||||
|
# Split IP/mask
|
||||||
|
if '/' in ip_with_mask:
|
||||||
|
ip = ip_with_mask.split('/')[0]
|
||||||
|
subnet = ip_with_mask.split('/')[1]
|
||||||
|
else:
|
||||||
|
ip = ip_with_mask
|
||||||
|
subnet = ""
|
||||||
|
|
||||||
|
print(f"{name:<{col_widths['interface']}} {ip:<{col_widths['ip']}} {subnet:<{col_widths['subnet']}} {mac:<{col_widths['mac']}}")
|
||||||
|
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']}}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error fetching details for {interface}: {e}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
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')
|
||||||
|
args = parser.parse_args()
|
||||||
|
display_interface_details(args.all)
|
6
config/home-manager/flake.lock
generated
6
config/home-manager/flake.lock
generated
@ -39,11 +39,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-unstable": {
|
"nixpkgs-unstable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1742669843,
|
"lastModified": 1742889210,
|
||||||
"narHash": "sha256-G5n+FOXLXcRx+3hCJ6Rt6ZQyF1zqQ0DL0sWAMn2Nk0w=",
|
"narHash": "sha256-hw63HnwnqU3ZQfsMclLhMvOezpM7RSB0dMAtD5/sOiw=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "1e5b653dff12029333a6546c11e108ede13052eb",
|
"rev": "698214a32beb4f4c8e3942372c694f40848b360d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user