Skip to content

Commit

Permalink
Merge pull request #51 from HPCNow/main
Browse files Browse the repository at this point in the history
froster v0.11.7
  • Loading branch information
victormachadoperez authored Jun 4, 2024
2 parents 62441ff + da328ae commit 68d9b11
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 77 deletions.
10 changes: 2 additions & 8 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,8 @@
name: Upload Python Package

on:
workflow_dispatch:
inputs:
logLevel:
description: 'Log level'
required: true
default: 'warning'
tags:
description: 'Test scenario tags'
release:
types: [created]

permissions:
contents: read
Expand Down
109 changes: 85 additions & 24 deletions froster/froster.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ def __init__(self):
if self.aws_profile and self.aws_region:
self.aws_init = True

# Last timestamp we checked for an updated
self.update_check_timestamp = config.get(
'UPDATE', 'timestamp', fallback=None)

# Shared configuration
self.is_shared = config.getboolean(
'SHARED', 'is_shared', fallback=False)
Expand Down Expand Up @@ -254,6 +258,7 @@ def __init__(self):

if self.user_init and self.aws_init and self.s3_init and self.nih_init:
self.configuration_done = True

except Exception:
print_error()

Expand Down Expand Up @@ -1197,6 +1202,27 @@ def set_slurm(self, args):
print_error()
return False

def check_update(self):
'''Set the update check'''

try:
timestamp = time.time()

if hasattr(self, 'update_check_timestamp') and self.update_check_timestamp is not None:
# Check if last day was less than 86400 * 7 = (1 day) * 7 = 1 week
if timestamp - self.update_check_timestamp < (86400*7):
# Less than a week since last check
return False

# Set the update check flag in the config file
self.__set_configuration_entry(
'UPDATE', 'update_check_timestamp', timestamp)
return True

except Exception:
print_error()
return False


class AWSBoto:
'''AWS handler class. This class is used to interact with AWS services.'''
Expand Down Expand Up @@ -6147,7 +6173,7 @@ def subcmd_index(self, cfg: ConfigManager, arch: Archiver):
except Exception:
print_error()

def subcmd_archive(self, arch: Archiver):
def subcmd_archive(self, arch: Archiver, aws: AWSBoto):
'''Check command for archiving folders for Froster.'''

try:
Expand All @@ -6174,6 +6200,10 @@ def subcmd_archive(self, arch: Archiver):
arch.reset_folder(folder, self.args.recursive)
return

if not aws.check_credentials():
print('\nError: invalid credentials. Check the AWS configuration with "froster config --aws"\n')
sys.exit(1)

# Check if the user provided the hotspots argument
if self.args.hotspots:
if self.args.folders:
Expand All @@ -6200,6 +6230,10 @@ def subcmd_restore(self, arch: Archiver, aws: AWSBoto):
'''Check command for restoring folders for Froster.'''

try:
if not aws.check_credentials():
print('\nError: invalid credentials. Check the AWS configuration with "froster config --aws"\n')
sys.exit(1)

if self.args.monitor:
# aws inactivity and cost monitoring
aws.monitor_ec2()
Expand Down Expand Up @@ -6235,10 +6269,14 @@ def subcmd_restore(self, arch: Archiver, aws: AWSBoto):
except Exception:
print_error()

def subcmd_delete(self, arch: Archiver):
def subcmd_delete(self, arch: Archiver, aws: AWSBoto):
'''Check command for deleting folders for Froster.'''

try:
if not aws.check_credentials():
print('\nError: invalid credentials. Check the AWS configuration with "froster config --aws"\n')
sys.exit(1)

if not self.args.folders:

# Get the list of folders from the archive
Expand Down Expand Up @@ -6269,9 +6307,13 @@ def subcmd_delete(self, arch: Archiver):
except Exception:
print_error()

def subcmd_mount(self, arch: Archiver):
def subcmd_mount(self, arch: Archiver, aws: AWSBoto):

try:
if not aws.check_credentials():
print('\nError: invalid credentials. Check the AWS configuration with "froster config --aws"\n')
sys.exit(1)

if self.args.list:
arch.print_current_mounts()
return
Expand Down Expand Up @@ -6413,26 +6455,40 @@ def subcmd_credentials(self, cfg: ConfigManager, aws: AWSBoto):
return False

def subcmd_update(self):
'''Update Froster'''

'''Check if an update is available'''
try:
if self.args.rclone:
cmd = "rclone selfupdate"
else:
cmd = "curl -s https://raw.githubusercontent.com/dirkpetersen/froster/main/install.sh?$(date +%s) | bash"

p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, shell=True)

for line in iter(p.stdout.readline, b''):
print(line.decode(), end='')

# Wait for the process to finish and get the exit code
p.wait()
cmd = "curl -s https://api.github.com/repos/dirkpetersen/froster/releases"

result = subprocess.run(cmd, shell=True, text=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)

if result.returncode != 0:
print(f"Error checking if froster update available. Command run: {cmd}: {result.stderr.strip()}")
return False

def compare_versions(version1, version2):
v1 = [int(v) for v in version1.split(".")]
v2 = [int(v) for v in version2.split(".")]

for i in range(max(len(v1), len(v2))):
v1_part = v1[i] if i < len(v1) else 0
v2_part = v2[i] if i < len(v2) else 0
if v1_part != v2_part:
return v1_part - v2_part
return 0

releases = json.loads(result.stdout)
latest = releases[0]['tag_name'].replace('v', '')
current = pkg_resources.get_distribution("froster").version

if compare_versions(latest, current) > 0:
print(f'\nA froster update is available: froster v{latest}')
print(f'You can update froster using the command:')
print(f' curl -s https://raw.githubusercontent.com/dirkpetersen/froster/main/install.sh?$(date +%s) | bash\n')
else:
print(f'\nFroster is up to date: froster v{current}\n')

if p.returncode != 0:
print(
f"Error: The update failed with exit code {p.returncode}.")
except Exception:
print_error()

Expand Down Expand Up @@ -6871,15 +6927,15 @@ def main():
elif args.subcmd in ['index', 'ind']:
cmd.subcmd_index(cfg, arch)
elif args.subcmd in ['archive', 'arc']:
cmd.subcmd_archive(arch)
cmd.subcmd_archive(arch, aws)
elif args.subcmd in ['restore', 'rst']:
cmd.subcmd_restore(arch, aws)
elif args.subcmd in ['delete', 'del']:
cmd.subcmd_delete(arch)
cmd.subcmd_delete(arch, aws)
elif args.subcmd in ['mount', 'mnt']:
cmd.subcmd_mount(arch)
cmd.subcmd_mount(arch, aws)
elif args.subcmd in ['umount']:
cmd.subcmd_umount(arch)
cmd.subcmd_umount(arch, aws)
elif args.subcmd in ['ssh', 'scp']:
cmd.subcmd_ssh(cfg, aws)
elif args.subcmd in ['credentials', 'crd']:
Expand All @@ -6889,6 +6945,11 @@ def main():
else:
cmd.print_help()

# Check if there are updates on froster every X days
if cfg.check_update():
cmd.subcmd_update(cfg)

# Close the AWS session
aws.close_session()

except Exception:
Expand Down
21 changes: 6 additions & 15 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,9 @@ backup_old_installation() {
fi

if pipx list | grep froster >/dev/null 2>&1; then
pipx uninstall froster &
# If froster is installed with pipx, uninstall it and ignore errors
# sometime pipx uninstall fails with error code 1 if PIPX_HOME is set, but froster is still uninstalled
pipx uninstall froster >/dev/null 2>&1 &
spinner $!
fi

Expand Down Expand Up @@ -234,22 +236,11 @@ install_froster() {
# Ensure ~/.local/bin is in the PATH
pipx ensurepath >/dev/null 2>&1

# TODO: Update path once froster is in PyPi repository

# Get the repository and branch from the github environment variables (if any)
# or set the default repository and branch
if [[ -v REPO ]]; then
REPO="https://github.com/$REPO"
else
REPO="https://github.com/dirkpetersen/froster.git"
fi

BRANCH=${BRANCH:-"main"}

echo
echo "Installing latest version of froster from \"$REPO@$BRANCH\"..."
echo "Installing latest version of froster..."

pipx install git+$REPO@$BRANCH >/dev/null 2>&1 &
# Install froster from PyPi package repository
pipx install froster >/dev/null 2>&1 &
spinner $!

# Keep the config.ini file (if any)
Expand Down
24 changes: 24 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "froster"
version = "0.11.7"
description = "Froster is a tool for easy data transfer between local file systems and AWS S3 storage."
authors = ["Victor Machado <[email protected]>"]
readme = "README.md"
license = "MIT"

[tool.poetry.dependencies]
python = "^3.6"
boto3 = "^1.34.104"
duckdb = "^0.10.2"
inquirer = "^3.2.4"
psutil = "^5.9.0"
requests = "^2.31.0"
textual = "^0.59.0"
visidata = "^3.0.2"

[tool.poetry.scripts]
froster = "froster.froster:main"
7 changes: 0 additions & 7 deletions requirements.txt

This file was deleted.

23 changes: 0 additions & 23 deletions setup.py

This file was deleted.

0 comments on commit 68d9b11

Please sign in to comment.