commit 2742e0cdffca1ff9bff0d640fae3fa4f936fe302 Author: Antonio de la Rosa Date: Thu Dec 11 17:11:19 2025 +0100 First files diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af2f537 --- /dev/null +++ b/.gitignore @@ -0,0 +1,104 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +.static_storage/ +.media/ +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..1361668 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Utils for scripts in *nix like systems. diff --git a/cuchulucputils/__init__.py b/cuchulucputils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cuchulucputils/linux.py b/cuchulucputils/linux.py new file mode 100644 index 0000000..32570ef --- /dev/null +++ b/cuchulucputils/linux.py @@ -0,0 +1,136 @@ +#!/usr/bin/python3 + +import os +import distro +from subprocess import call, DEVNULL +import re +import json + +def shell_command(command): + + return_call=call(command, shell=True) + + if return_call> 0: + print('Error: cannot execute command '+command+' with return code '+str(return_call)+'\n') + return False + else: + return True + +def check_distro(arr_command): + + distro_id=distro.id() + + if not distro_id in arr_command: + + print("Sorry, you cannot get the distro\n\n") + + return False + else: + return distro_id + +def install_package(package): + + distro_id=distro.id() + + if distro_id=='debian' or distro_id=='ubuntu': + + return shell_command('sudo DEBIAN_FRONTEND="noninteractive" apt-get install -y {}'.format(package[distro_id])) + + elif distro_id=='fedora' or distro_id=='almalinux' or distro_id=='rocky' or distro_id=='centos': + + return shell_command('sudo dnf install -y {}'.format(package[distro_id])) + + elif distro_id=='arch': + + return shell_command('sudo pacman -S --noconfirm {}'.format(package[distro_id])) + + +def patch_file(original_file, patch_file, no_patch_distro=True): + + distro_id=check_distro(original_file) + + if not distro_id: + + if no_patch_distro: + + print('This distro ignored for patch') + + return True + else: + + print('This distro need a patch') + + return False + + if distro_id in original_file: + + return shell_command("sudo patch {} < {}".format(original_file[distro_id], patch_file[distro_id])) + else: + + print('Ignored file for patching for distro '+distro_id) + + return True + + +def systemd_service(action, service): + + distro_id=check_distro(service) + + if not distro_id: + + return False + + if distro_id in service: + + return shell_command('sudo systemctl {} {}'.format(action, service[distro_id])) + + else: + + print('Cannot restart service') + + return True + +def exec(command): + + distro_id=check_distro(command) + + if not distro_id: + + return False + + if distro_id in command: + + return shell_command(command[distro_id]) + + else: + + print('Cannot execute the command in this distro') + + return True + + +def sed(arr_sed): + + distro_id=check_distro(arr_sed) + + if not distro_id: + + return 0 + + return shell_command("sudo sed -i \"s/{}/{}/g\" {}".format(arr_sed[distro_id][0], arr_sed[distro_id][1], arr_sed[distro_id][2])) + + +def json_log(message, error=0, status=0, progress=0, no_progress=0, return_message=0, result=None): + + log={'error': error, 'status': status, 'progress': progress, 'no_progress': no_progress, 'message': message} + + if result: + log['result']=result + + if not return_message: + + print(json.dumps(log)) + + else: + return json.dumps(log) + diff --git a/cuchulucputils/packages.py b/cuchulucputils/packages.py new file mode 100644 index 0000000..2286990 --- /dev/null +++ b/cuchulucputils/packages.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 + +import os +import distro +from subprocess import call, DEVNULL +import re + +def install_package(package: dict, extra_configurations={}): + + """A function for install packages for different distros. Now support, debian, ubuntu, rocky, almalinux, fedora, archlinux. + + Args: + package (dict): A dict with all packages names for every distro. + + Returns: + + result_package_manager (bool): return false if install fail, if install is finished, return true. + """ + + linux_distro=distro.id() + + if not linux_distro in package: + print('Sorry, not package in {}'.format(linux_distro)) + return False + + if linux_distro=='debian' or linux_distro=='ubuntu': + + if call('sudo DEBIAN_FRONTEND="noninteractive" apt-get install -y {}'.format(package[linux_distro]), shell=True) > 0: + print('Error, cannot install {}...'.format(package[linux_distro])) + return False + + elif linux_distro=='rocky' or linux_distro=='fedora' or linux_distro=='almalinux': + + if call("sudo dnf install -y {}".format(package[linux_distro]), shell=True) > 0: + print('Error, cannot install {}...'.format(package[linux_distro])) + return False + if linux_distro=='arch': + + if call("sudo pacman -S --noconfirm {}".format(package[linux_distro]), shell=True) > 0: + print('Error, cannot install {}...'.format(package[linux_distro])) + return False + +# Method for patch files using patch utility + +def apply_patch(original_file: dict, patch_file: dict): + + linux_distro=distro.id() + + # patch originalAmigo.sh < parche.patch + + if not linux_distro in original_file or not linux_distro in patch_file): + print('Error, not exists original file and patch files for this distro')) + return False + + if call("sudo patch {} < {}".format(original_file[linux_distro], patch_file[linux_distro]), shell=True) > 0: + print('Error, cannot patch {}...'.format(original_file[linux_distro])) + return False +# A simple function for fill an array for every distros with the same package name. + +def fill_all_distros_str(name): + + fill_str={} + + for distro in ['debian', 'ubuntu', 'rocky', 'almalinux', 'fedora', 'arch']: + fill_str[distro]=name + + return fill_str + +# A simple function for get a json return value + +def return_json_value(): + + return {} diff --git a/cuchulucputils/unix.py b/cuchulucputils/unix.py new file mode 100644 index 0000000..781925c --- /dev/null +++ b/cuchulucputils/unix.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 + +import time +import os +import re +import argparse +import json +import pwd +import sys +import crypt +from subprocess import call, DEVNULL + +def add_user(user, password='', group='', user_directory='', shell='/usr/sbin/nologin'): + + if user_directory=='': + user_directory='/home/'+user + + try: + user_pwd=pwd.getpwnam(user) + + return (False, 'User exists') + + except KeyError: + + # add user + + if password!='': + + salt=crypt.mksalt(crypt.METHOD_SHA512) + + password='-p \"%s\"' % crypt.crypt(password, salt).replace('$', '\$') + + if group!='': + + # Buggy, need fix. + + stat_group=os.stat('/home/%s' % user_directory) + gid=stat_group.st_gid + + func_user="sudo useradd -m -s %s -g %i %s -d %s %s" % (shell, gid, password, user_directory, user) + + else: + + func_user="sudo useradd -m -s %s %s -d %s %s" % (shell, password, user_directory, user) + + if call(func_user, shell=True, stdout=DEVNULL) > 0: + + return (False, 'Error executing useradd command') + + else: + + return (True, '') + + + +def change_password(user, new_password): + + try: + user_pwd=pwd.getpwnam(user) + + if call("sudo echo \"%s:%s\" | sudo chpasswd" % (user, new_password), shell=True, stdout=DEVNULL) > 0: + + return (False, 'I cannot change password, permissions?') + + else: + return (True, 'Change password successfully') + + + except KeyError: + + return (False, 'I cannot change password, user exists?') + +def del_user(user): + + if call("sudo userdel -r %s" % user, shell=True, stdout=DEVNULL, stderr=DEVNULL) > 0: + return (False, '') + else: + return (True, 'Deleted user successfully') + +def mkdir_sh(directory): + + if call("sudo mkdir -p %s" % directory, shell=True) > 0: + return (False, '') + else: + return (True, 'Created directory successfully %s' % directory) + diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..d1b45e6 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,34 @@ +[build-system] +requires = ["flit_core >=3.2,<4"] +build-backend = "flit_core.buildapi" + +[project] +name = "pastafariutils" +authors = [{name = "Antonio de la Rosa", email = "antonio.delarosa@salirdelhoyo.com"}] +readme = "README.md" +version = "0.76.5" +description = "Utils for make *nix scripts." +# dynamic = ["version", "description"] + +classifiers=['Development Status :: 4 - Beta', + "Intended Audience :: Developers", + "License :: OSI Approved :: GNU Affero General Public License v3", + "Topic :: Software Development :: Libraries :: Utils for Linux servers", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13" +] + +requires-python = ">=3.9" + +dependencies=[ + "mako", + "jinja2" +] + +[project.urls] +Home = "https://git.cuchulu.com/paramecio/pastafariutils/" +# Documentation = "https://docs.cuchulu.com/paramecio2/" diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..8c28267 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,3 @@ +[metadata] +description-file = README.md + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..74a526f --- /dev/null +++ b/setup.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 + +import sys +import os +from setuptools import setup, find_packages + + +if sys.version_info < (3, 9): + raise NotImplementedError("Sorry, you need at least Python 3.9 for use cuchulucputils.") + +setup(name='cuchulucputils', + version='0.76.5', + description='Utils for make *nix scripts.', + long_description='Utils for make *nix scripts.', + author='Antonio de la Rosa Caballero', + author_email='antonio.delarosa@salirdelhoyo.com', + url='https://git.cuchulu.com/paramecio/cuchulucputils', + packages=['cuchulucputils'], + include_package_data=True, + install_requires=[], + license='GPLV3', + platforms = 'any', + classifiers=['Development Status :: 1 - Beta', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: GPLV2 License', + 'Topic :: Software Development :: Libraries :: Utils for Linux servers', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9' , + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12' + 'Programming Language :: Python :: 3.13' + ], + )