Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3.6.0 #77

Merged
merged 1 commit into from
Nov 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ jobs:
release_name: ${{ env.VERSION }}
body: |
**Changes**:
- Added a way to specify SMTP host and port for mail report sending
- Requests from reposerver now support more options like dry-run, keep old config files, etc...
- Various typo fixes
draft: false
prerelease: false

Expand Down
2 changes: 1 addition & 1 deletion linupdate.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def main():
# Execute packages update
my_package.update(my_args.packages_to_update,
my_args.assume_yes,
my_args.ignore_exclude,
my_args.ignore_exclusions,
my_args.check_updates,
my_args.dist_upgrade,
my_args.keep_oldconf,
Expand Down
11 changes: 11 additions & 0 deletions src/controllers/App/Utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,14 @@ def clean_log(self, text):
text = text.strip()

return text

#-----------------------------------------------------------------------------------------------
#
# Convert a string to a boolean
#
#-----------------------------------------------------------------------------------------------
def stringToBoolean(self, value: str):
if value == 'true' or value == 'True':
return True

return False
12 changes: 6 additions & 6 deletions src/controllers/Args.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def parse(self):
# Default values
Args.assume_yes = False
Args.check_updates = False
Args.ignore_exclude = False
Args.ignore_exclusions = False
Args.packages_to_update = []
Args.dist_upgrade = False
Args.keep_oldconf = True
Expand Down Expand Up @@ -95,7 +95,7 @@ def parse(self):
# Check updates
parser.add_argument("--check-updates", "-cu", action="store_true", default="null")
# Ignore exclude
parser.add_argument("--ignore-exclude", "-ie", action="store_true", default="null")
parser.add_argument("--ignore-exclusions", "-ie", action="store_true", default="null")
# Exit on package update error
parser.add_argument("--exit-on-package-update-error", action="store", nargs='?', default="null")

Expand Down Expand Up @@ -367,10 +367,10 @@ def parse(self):
Args.dry_run = True

#
# If --ignore-exclude param has been set
# If --ignore-exclusions param has been set
#
if args.ignore_exclude != "null":
Args.ignore_exclude = True
if args.ignore_exclusions != "null":
Args.ignore_exclusions = True

#
# If --check-updates param has been set
Expand Down Expand Up @@ -742,7 +742,7 @@ def help(self):
},
{
'args': [
'--ignore-exclude',
'--ignore-exclusions',
'-ie'
],
'description': 'Ignore all package exclusions'
Expand Down
47 changes: 37 additions & 10 deletions src/controllers/Module/Reposerver/Agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,12 @@ def websocket_on_message(self, ws, message):
status = None
error = None

# Update parameters default values
dry_run = False
ignore_exclusions = False
keep_oldconf = True
full_upgrade = False

# Decode JSON message
message = json.loads(message)

Expand Down Expand Up @@ -327,42 +333,63 @@ def websocket_on_message(self, ws, message):
with Log(log):
self.reposerverStatusController.send_packages_info()

# Case the request is 'update-all-packages', then update all packages
elif message['request'] == 'update-all-packages':
# Case the request is 'request-all-packages-update', then update all packages
elif message['request'] == 'request-all-packages-update':
print('[reposerver-agent] Reposerver requested all packages update')

# Try to retrieve the update params
if 'data' in message:
if 'update-params' in message['data']:
if 'dry-run' in message['data']['update-params']:
dry_run = Utils().stringToBoolean(message['data']['update-params']['dry-run'])
if 'ignore-exclusions' in message['data']['update-params']:
ignore_exclusions = Utils().stringToBoolean(message['data']['update-params']['ignore-exclusions'])
if 'keep-config-files' in message['data']['update-params']:
keep_oldconf = Utils().stringToBoolean(message['data']['update-params']['keep-config-files'])
if 'full-upgrade' in message['data']['update-params']:
full_upgrade = Utils().stringToBoolean(message['data']['update-params']['full-upgrade'])

# Send a response to the reposerver to make the request as running
self.set_request_status(request_id, 'running')

# Log everything to the log file
with Log(log):
self.packageController.update([], True)
self.packageController.update([], True, ignore_exclusions, False, full_upgrade, keep_oldconf, dry_run)

# TODO
# Take into account the --dry-run option
# Restart/reload services if the user said so
# Execute reposever post-update actions

# Send a summary to the reposerver, with the summary of the update (number of packages updated or failed)
summary = self.packageController.summary

# Case the request is 'request-specific-packages-installation', then update a list of packages
# Case the request is 'request-packages-update', then update a list of specific packages
# A list of packages must be provided in the message
elif message['request'] == 'request-specific-packages-installation':
elif message['request'] == 'request-packages-update':
print('[reposerver-agent] Reposerver requested to update a list of packages')
# Try to retrieve the update packages and params
if 'data' in message:
if 'update-params' in message['data']:
if 'dry-run' in message['data']['update-params']:
dry_run = Utils().stringToBoolean(message['data']['update-params']['dry-run'])
if 'ignore-exclusions' in message['data']['update-params']:
ignore_exclusions = Utils().stringToBoolean(message['data']['update-params']['ignore-exclusions'])
if 'keep-config-files' in message['data']['update-params']:
keep_oldconf = Utils().stringToBoolean(message['data']['update-params']['keep-config-files'])
if 'full-upgrade' in message['data']['update-params']:
full_upgrade = Utils().stringToBoolean(message['data']['update-params']['full-upgrade'])

# If a list of packages is provided, then the update can be performed
if 'packages' in message['data'] and len(message['data']['packages']) > 0:
print('[reposerver-agent] Reposerver requested to update a list of packages')

# Send a response to the reposerver to make the request as running
self.set_request_status(request_id, 'running')

# Log everything to the log file
with Log(log):
self.packageController.update(message['data']['packages'], True)
self.packageController.update(message['data']['packages'], True, ignore_exclusions, False, full_upgrade, keep_oldconf, dry_run)

# Send a summary to the reposerver, with the summary of the installation (number of packages installed or failed)
summary = self.packageController.summary

else:
raise Exception('unknown request sent by reposerver: ' + message['request'])

Expand Down
10 changes: 5 additions & 5 deletions src/controllers/Module/Reposerver/Status.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def send_general_info(self):

try:
self.httpRequestController.quiet = False
self.httpRequestController.put(url + '/api/v2/host/status', id, token, data)
self.httpRequestController.put(url + '/api/v2/host/status', id, token, data, 5, 10)
except Exception as e:
raise Exception('error while sending general status to reposerver: ' + str(e))

Expand Down Expand Up @@ -103,7 +103,7 @@ def sendAvailablePackagesStatus(self):

for package in packages:
name = package['name']
available_version = package['available_version']
available_version = package['target_version']

# Ignore package if name is empty
if name == '':
Expand Down Expand Up @@ -134,7 +134,7 @@ def sendAvailablePackagesStatus(self):
print(' Sending available packages to ' + Fore.YELLOW + url + Style.RESET_ALL + ':')

self.httpRequestController.quiet = False
self.httpRequestController.put(url + '/api/v2/host/packages/available', id, token, data)
self.httpRequestController.put(url + '/api/v2/host/packages/available', id, token, data, 5, 10)


#-----------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -184,7 +184,7 @@ def sendInstalledPackagesStatus(self):
print(' Sending installed packages to ' + Fore.YELLOW + url + Style.RESET_ALL + ':')

self.httpRequestController.quiet = False
self.httpRequestController.put(url + '/api/v2/host/packages/installed', id, token, data)
self.httpRequestController.put(url + '/api/v2/host/packages/installed', id, token, data, 5, 10)


#-----------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -235,4 +235,4 @@ def send_packages_history(self, entries_limit: int = 999999):
print(' Sending packages events to ' + Fore.YELLOW + url + Style.RESET_ALL + ':')

self.httpRequestController.quiet = False
self.httpRequestController.put(url + '/api/v2/host/packages/event', id, token, events)
self.httpRequestController.put(url + '/api/v2/host/packages/event', id, token, events, 5, 10)
27 changes: 15 additions & 12 deletions src/controllers/Package/Apt.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def get_available_packages(self, dist_upgrade: bool = False):
myPackage = {
'name': pkg.name,
'current_version': pkg.installed.version,
'available_version': pkg.candidate.version
'target_version': pkg.candidate.version
}

list.append(myPackage)
Expand Down Expand Up @@ -301,7 +301,7 @@ def update(self, packagesList, exit_on_package_update_error: bool = True, dry_ru
Path(log).unlink()

with Log(log):
print('\n ▪ Updating ' + Fore.GREEN + pkg['name'] + Style.RESET_ALL + ' (' + pkg['current_version'] + ' → ' + pkg['available_version'] + '):')
print('\n ▪ Updating ' + Fore.GREEN + pkg['name'] + Style.RESET_ALL + ' (' + pkg['current_version'] + ' → ' + pkg['target_version'] + '):')

# Before updating, check If package is already in the latest version, if so, skip it
# It means that it has been updated previously by another package, probably because it was a dependency
Expand All @@ -311,15 +311,15 @@ def update(self, packagesList, exit_on_package_update_error: bool = True, dry_ru
temp_apt_cache.open(None)

# If version in cache is the same the target version, skip the update
if temp_apt_cache[pkg['name']].installed.version == pkg['available_version']:
if temp_apt_cache[pkg['name']].installed.version == pkg['target_version']:
print(Fore.GREEN + ' ✔ ' + Style.RESET_ALL + pkg['name'] + ' is already up to date (updated with another package).')

# Mark the package as already updated
self.summary['update']['success']['count'] += 1

# Also add the package to the list of successful packages
self.summary['update']['success']['packages'][pkg['name']] = {
'version': pkg['available_version'],
'version': pkg['target_version'],
'log': 'Already up to date (updated with another package).'
}

Expand All @@ -332,17 +332,20 @@ def update(self, packagesList, exit_on_package_update_error: bool = True, dry_ru
# If --keep-oldconf is True, then keep the old configuration file
if self.keep_oldconf:
cmd = [
'apt-get', 'install', pkg['name'] + '=' + pkg['available_version'], '-y',
# Debug only
# '--dry-run',
'apt-get', 'install', pkg['name'] + '=' + pkg['target_version'], '-y',
'-o', 'Dpkg::Options::=--force-confdef',
'-o', 'Dpkg::Options::=--force-confold'
'-o', 'Dpkg::Options::=--force-confold',
# Debug only
# '--dry-run'
]
else:
cmd = ['apt-get', 'install', pkg['name'] + '=' + pkg['available_version'], '-y']
cmd = ['apt-get', 'install', pkg['name'] + '=' + pkg['target_version'], '-y',
# Debug only
# '--dry-run'
]

# If --dry-run is True, then simulate the update
if dry_run:
if dry_run == True:
cmd.append('--dry-run')

popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
Expand Down Expand Up @@ -372,7 +375,7 @@ def update(self, packagesList, exit_on_package_update_error: bool = True, dry_ru

# Add the package to the list of failed packages
self.summary['update']['failed']['packages'][pkg['name']] = {
'version': pkg['available_version'],
'version': pkg['target_version'],
'log': log_content
}

Expand All @@ -393,7 +396,7 @@ def update(self, packagesList, exit_on_package_update_error: bool = True, dry_ru

# Add the package to the list of successful packages
self.summary['update']['success']['packages'][pkg['name']] = {
'version': pkg['available_version'],
'version': pkg['target_version'],
'log': log_content
}

Expand Down
16 changes: 8 additions & 8 deletions src/controllers/Package/Dnf.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def get_available_packages(self, useless_dist_upgrade: bool = False):
list.append({
'name': package[0],
'current_version': current_version,
'available_version': package[1],
'target_version': package[1],
'repository': package[2]
})

Expand Down Expand Up @@ -306,7 +306,7 @@ def update(self, packagesList, exit_on_package_update_error: bool = True, dry_ru
Path(log).unlink()

with Log(log):
print('\n ▪ Updating ' + Fore.GREEN + pkg['name'] + Style.RESET_ALL + ' (' + pkg['current_version'] + ' → ' + pkg['available_version'] + '):')
print('\n ▪ Updating ' + Fore.GREEN + pkg['name'] + Style.RESET_ALL + ' (' + pkg['current_version'] + ' → ' + pkg['target_version'] + '):')

# Before updating, check if package is already in the latest version, if so, skip it
# It means that it has been updated previously by another package, probably because it was a dependency
Expand All @@ -327,26 +327,26 @@ def update(self, packagesList, exit_on_package_update_error: bool = True, dry_ru
current_version = result.stdout.strip()

# If current version is the same the target version, skip the update
if current_version == pkg['available_version']:
if current_version == pkg['target_version']:
print(Fore.GREEN + ' ✔ ' + Style.RESET_ALL + pkg['name'] + ' is already up to date (updated with another package).')

# Mark the package as already updated
self.summary['update']['success']['count'] += 1

# Also add the package to the list of successful packages
self.summary['update']['success']['packages'][pkg['name']] = {
'version': pkg['available_version'],
'version': pkg['target_version'],
'log': 'Already up to date (updated with another package).'
}

# Continue to the next package
continue

# Define the command to update the package
cmd = ['dnf', 'update', pkg['name'] + '-' + pkg['available_version'], '-y']
cmd = ['dnf', 'update', pkg['name'] + '-' + pkg['target_version'], '-y']

# If dry_run is True, add the --setopt tsflags=test option to simulate the update
if dry_run:
if dry_run == True:
cmd.append('--setopt')
cmd.append('tsflags=test')

Expand All @@ -371,7 +371,7 @@ def update(self, packagesList, exit_on_package_update_error: bool = True, dry_ru

# Add the package to the list of failed packages
self.summary['update']['failed']['packages'][pkg['name']] = {
'version': pkg['available_version'],
'version': pkg['target_version'],
'log': log_content
}

Expand All @@ -392,7 +392,7 @@ def update(self, packagesList, exit_on_package_update_error: bool = True, dry_ru

# Add the package to the list of successful packages
self.summary['update']['success']['packages'][pkg['name']] = {
'version': pkg['available_version'],
'version': pkg['target_version'],
'log': log_content
}

Expand Down
Loading