Skip to content

Commit

Permalink
Fix flag parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
Boernsman committed Oct 4, 2024
1 parent f8b22a5 commit a75f8a3
Show file tree
Hide file tree
Showing 14 changed files with 689 additions and 122 deletions.
39 changes: 39 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Use the official Go image to build the application
FROM golang:1.22 AS builder

# Set the Current Working Directory inside the container
WORKDIR /app

# Copy go.mod and go.sum to install dependencies
COPY go.mod go.sum ./

# Download all dependencies. They will be cached if the go.mod and go.sum files are not changed.
RUN go mod download

# Copy the source code into the container
COPY . .

# Build the Go application
RUN go build -o whereisit .

# Use a smaller image for deployment
FROM alpine:3.18

# Install certificates for HTTPS
RUN apk --no-cache add ca-certificates

# Create a folder for certificates (assuming you have your own SSL cert and key)
RUN mkdir -p /etc/ssl/certs && mkdir -p /etc/ssl/private

# Copy the SSL certificates (adjust paths as necessary)
COPY ./certs/server.crt /etc/ssl/certs/
COPY ./certs/server.key /etc/ssl/private/

# Copy the built Go binary from the builder
COPY --from=builder /app/main /app/main

# Expose HTTP on port 80 and HTTPS on port 443
EXPOSE 80 443

# Command to run the executable
CMD ["/app/whereisit"]
117 changes: 117 additions & 0 deletions examples/python/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import argparse
import requests
import json
import time
import socket
import os

STATE_FILE = "/tmp/ip_state.json" # Store the last IP and timestamp

def get_local_ip():
"""
Retrieve the current local IP address.
"""
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# This doesn't actually send data; it's just to get the IP
s.connect(('8.8.8.8', 80))
return s.getsockname()[0]
except Exception as e:
print(f"Error retrieving local IP: {e}")
return None
finally:
s.close()

def get_hostname():
"""
Retrieve the local machine's hostname.
"""
return socket.gethostname()

def get_serial_number():
"""
Retrieve the device's serial number.
This is an example command that works on many Linux systems.
Adjust as needed based on your hardware.
"""
try:
# This command works on many Linux systems
serial = os.popen("cat /etc/machine-id").read().strip()
if not serial:
serial = "UNKNOWN_SERIAL"
return serial
except Exception as e:
print(f"Error retrieving serial number: {e}")
return "UNKNOWN_SERIAL"

def load_state():
"""
Load the last known state (IP and timestamp) from file.
"""
if os.path.exists(STATE_FILE):
with open(STATE_FILE, 'r') as f:
return json.load(f)
return None

def save_state(ip, timestamp):
"""
Save the current IP and timestamp to file.
"""
with open(STATE_FILE, 'w') as f:
json.dump({"ip": ip, "timestamp": timestamp}, f)


def send_ip_update(ip, name, id, server_ip, server_port):
"""
Send the local IP to the REST server as a JSON payload.
"""
url = f"http://{server_ip}:{server_port}/api/register"
payload = {
"name": name,
"address": ip,
"id": id
}
try:
response = requests.post(url, json=payload)
if response.status_code == 200:
print(f"Successfully sent IP update to {server_ip}:{server_port}: {ip}")
else:
print(f"Failed to send IP update. Status code: {response.status_code}")
except Exception as e:
print(f"Error sending IP update: {e}")

def main():
# Parse command line arguments
parser = argparse.ArgumentParser(description="Send local IP to a \"whereisit\" server when it changes, or every 24 hours.")
parser.add_argument("--server-ip", required=True, help="The IP address of the REST server.")
parser.add_argument("--server-port", required=True, help="The port number of the REST server.")
args = parser.parse_args()
server_ip = args.server_ip
server_port = args.server_port

while True:
current_ip = get_local_ip()

if not current_ip:
print("Could not determine local IP. Retrying in 10 minutes.")
time.sleep(600) # Retry in 10 minutes
continue

hostname = get_hostname()
identifier = get_serial_number()

state = load_state()
current_time = time.time()

# Check if state exists and if 24 hours have passed or IP has changed
if not state or state['ip'] != current_ip or (current_time - state['timestamp'] > 86400):
send_ip_update(current_ip, hostname, identifier, server_ip, server_port)
save_state(current_ip, current_time)
else:
print(f"No changes in IP. Last sent IP: {state['ip']}. Will check again in 10 minutes.")

# Wait 10 minutes before checking again
time.sleep(600)

if __name__ == "__main__":
main()
40 changes: 40 additions & 0 deletions examples/python/find.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import argparse
import requests

from typing import List

def get_devices(server_ip, server_port) -> List[str]:
"""
Send the local IP to the REST server as a JSON payload.
"""
url = f"http://{server_ip}:{server_port}/api/devices"
try:
response = requests.get(url)
if response.status_code == 200:
print(f"Successfully sent IP update to {server_ip}:{server_port}: {ip}")
print(response.content)
else:
print(f"Failed to send IP update. Status code: {response.status_code}")
except Exception as e:
print(f"Error sending IP update: {e}")

def main():
# Parse command line arguments
parser = argparse.ArgumentParser(description="Get devices inside the network from a \"whereisit\" server.")
parser.add_argument("--server-ip", required=True, help="The IP address of the REST server.")
parser.add_argument("--server-port", required=True, help="The port number of the REST server.")
parser.add_argument("--identifier", required=False, help="The identifier of the device searched for.")
args = parser.parse_args()
server_ip = args.server_ip
server_port = args.server_port

deviceList = get_devices(server_ip, server_port)

if deviceList.count > 0:
for device in deviceList:
print("Device:", device)
else:
print("No device found")

if __name__ == "__main__":
main()
99 changes: 99 additions & 0 deletions examples/sh/client.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env sh

DEVICE_NAME=$(hostname)

get_serial_number() {
local serial_number=""

# Detect operating system
os_name=$(uname)
if [[ "$os_name" == "Darwin" ]]; then
serial_number=$(system_profiler SPHardwareDataType | grep "Serial Number (system)" | awk '{print $NF}')
elif [[ "$os_name" == "Linux" ]]; then
serial_number=$(cat /etc/machine-id)
else
echo "Unsupported operating system: $os_name"
return 1
fi
echo "$serial_number"
}

get_lan_ip() {
local ip_address=""

# Detect operating system
os_name=$(uname)

if [[ "$os_name" == "Darwin" ]]; then
# macOS - Get LAN IP using ifconfig
ip_address=$(ifconfig en0 | grep "inet " | awk '{print $2}')
elif [[ "$os_name" == "Linux" ]]; then
# Linux - Get LAN IP using hostname or ip command
if command -v ip &> /dev/null; then
ip_address=$(ip addr show $(ip route show default | awk '/default/ {print $5}') | grep 'inet ' | awk '{print $2}' | cut -d/ -f1)
else
ip_address=$(hostname -I | awk '{print $1}')
fi
else
echo "Unsupported operating system: $os_name"
return 1
fi

echo "$ip_address"
}

get_os_version() {
OS_TYPE=$(uname)

if [[ "$OS_TYPE" == "Darwin" ]]; then
# macOS (Darwin) version
OS_VERSION=$(sw_vers -productVersion)
echo "Operating System: macOS"
echo "Version: $OS_VERSION"
elif [[ "$OS_TYPE" == "Linux" ]]; then
# Linux version
if [ -f /etc/os-release ]; then
. /etc/os-release
echo "Operating System: $NAME"
echo "Version: $VERSION"
else
echo "Operating System: Linux"
echo "Version information not found."
fi
else
echo "Unsupported operating system: $OS_TYPE"
return 1
fi
}

DEVICE_ID=$(get_serial_number)
DEVICE_IP=$(get_lan_ip)

if [ "$#" -ne 2 ]; then
echo "Usage: $0 <server_ip> <server_port>"
exit 1
fi

SERVER_IP=$1
SERVER_PORT=$2

PAYLOAD=$(cat <<EOF
{
"name": "${DEVICE_NAME}",
"id": "${DEVICE_ID}",
"address": "${DEVICE_IP}"
}
EOF
)
HEADERS="-H 'Content-Type: application/json'"

if [[ "$server_ip" == "localhost" || "$server_ip" == "127.0.0.1" ]]; then
headers+=" -H 'x-real-ip: ${DEVICE_IP}'"
fi

WHEREISIT_URL="http://${SERVER_IP}:${SERVER_PORT}/api/register"

eval "curl -X POST $WHEREISIT_URL $HEADERS -d '$PAYLOAD'"

echo "Payload sent: ${PAYLOAD}"
echo "----- DONE -----"
13 changes: 13 additions & 0 deletions examples/sh/find.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env sh

if [ "$#" -ne 2 ]; then
echo "Usage: $0 <server_ip> <server_port>"
exit 1
fi

SERVER_IP=$1
SERVER_PORT=$2

curl -X GET "${SERVER_IP}:${SERVER_PORT}/api/devices"

echo "----- DONE -----"
13 changes: 13 additions & 0 deletions examples/systemd/whereisit_client.timer
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[Unit]
Description=whereistit client run every 2 hours

[Service]
ExecStart=/usr/local/bin/whereistit_client.sh

[Timer]
OnBootSec=3min
OnUnitActiveSec=2h
Persistent=true

[Install]
WantedBy=multi-user.target
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
module whereisit

go 1.22.4

require github.com/gorilla/mux v1.8.1

require (
github.com/stretchr/testify v1.9.0 // indirect
gopkg.in/ini.v1 v1.67.0
)
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
13 changes: 5 additions & 8 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,19 @@ if [[ $EUID -ne 0 ]]; then
exit 1
fi

# Build the Go binary (Optional step, assuming Go is installed)
echo "Building the Go binary..."
go build -o "${WORKING_DIR}/${BINARY_NAME}"
if systemctl is-active --quiet ${SERVICE_NAME}; then
echo "${SERVICE_NAME} is stopped."
systemctl stop ${SERVICE_NAME}
fi

# Copy the binary to /usr/local/bin/
echo "Installing ${BINARY_NAME} binary to ${BINARY_INSTALL_PATH}"
cp "${WORKING_DIR}/${BINARY_NAME}" "${BINARY_INSTALL_PATH}"

# Check if the copy was successful
if [[ $? -ne 0 ]]; then
echo "Failed to install binary. Exiting."
exit 1
fi

# Copy the static files to /var/www/whereisit/public
echo "Creating web content directory at ${PUBLIC_DEST_DIR}"
mkdir -p "${PUBLIC_DEST_DIR}"

Expand All @@ -51,8 +49,7 @@ After=network.target
[Service]
Type=simple
ExecStart=${BINARY_INSTALL_PATH}${BINARY_NAME} --public ${PUBLIC_DEST_DIR}
WorkingDirectory=${PUBLIC_DEST_DIR}/../
ExecStart=${BINARY_INSTALL_PATH}${BINARY_NAME} --http-port 80 --public ${PUBLIC_DEST_DIR}
Restart=on-failure
User=$USER_NAME
Group=$USER_NAME
Expand Down
Loading

0 comments on commit a75f8a3

Please sign in to comment.