Last active
December 17, 2019 14:40
-
-
Save Jasata/8b7cb4a190ea47902df1bed8b8552476 to your computer and use it in GitHub Desktop.
Python class for configuration files (installation scripts run by root)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env python3 | |
# | |
# ConfigFile.py - Jani Tammi <jasata@utu.fi> | |
# | |
# NOTE: You obviously still need the proper privileges. | |
# You cannot run this as a regular user and set | |
# owner to be root and expect the .create() to | |
# actually manage that. | |
# THIS WAS WRITTEN PRIMARILY FOR INSTALLATION | |
# SCRIPTS THAT EXECUTE AS ROOT !! | |
# | |
import os | |
import pwd | |
import grp | |
import getpass | |
class ConfigFile: | |
"""As everything in this script, assumes superuser privileges. Only filename and content are required. User and group will default to effective user and group values on creation time and permissions default to common text file permissions wrxwr-wr- (0o644). | |
Properties: | |
name str Full path and name | |
owner str Username ('pi', 'www-data', etc) | |
group str Group ('pi', ...) | |
uid int User ID | |
gid int Group ID | |
permissions int File permissions. Use octal; 0o644 | |
content str This class was written to handle config files | |
Once properties and content are satisfactory, write the file to disk: | |
myFile = File(...) | |
myFile.create(overwrite = True) | |
If you wish the write to fail when the target file already exists, just leave out the 'overwrite'. | |
""" | |
def __init__( | |
self, | |
name: str, | |
content: str, | |
owner: str = None, | |
group: str = None, | |
permissions: int = 0o644 | |
): | |
# Default to effective UID/GID | |
owner = pwd.getpwuid(os.geteuid()).pw_name if not owner else owner | |
group = grp.getgrgid(os.getegid()).gr_name if not group else group | |
self.name = name | |
self._owner = owner | |
self._group = group | |
self._uid = pwd.getpwnam(owner).pw_uid | |
self._gid = grp.getgrnam(group).gr_gid | |
self.permissions = permissions | |
self.content = content | |
def create(self, overwrite = False, createdirs = True): | |
if createdirs: | |
path = os.path.split(self.name)[0] | |
if path: | |
os.makedirs(path, exist_ok = True) | |
mode = "x" if not overwrite else "w+" | |
with open(self.name, mode) as file: | |
file.write(self.content) | |
os.chmod(self.name, self.permissions) | |
os.chown(self.name, self._uid, self._gid) | |
def replace(self, key: str, value: str): | |
self.content = self.content.replace(key, value) | |
@property | |
def owner(self) -> str: | |
return self._owner | |
@owner.setter | |
def owner(self, name: str): | |
self._uid = pwd.getpwnam(name).pw_uid | |
self._owner = name | |
@property | |
def group(self) -> str: | |
return self._group | |
@group.setter | |
def group(self, name: str): | |
self._gid = grp.getgrnam(name).gr_gid | |
self._group = name | |
@property | |
def uid(self) -> int: | |
return self._uid | |
@uid.setter | |
def uid(self, uid: int): | |
self._uid = uid | |
self._owner = pwd.getpwuid(uid).pw_name | |
@property | |
def gid(self) -> int: | |
return self._gid | |
@gid.setter | |
def gid(self, gid: int): | |
self._gid = gid | |
self._group = grp.getgrgid(gid).gr_name | |
def __str__(self): | |
return "{} {}({}).{}({}) {} '{}'". format( | |
oct(self.permissions), | |
self._owner, self._uid, | |
self._group, self._gid, | |
self.name, | |
(self.content[:20] + '..') if len(self.content) > 20 else self.content | |
) | |
# Recommended way to have config files in your installer script | |
files = {} | |
files['nginx.site'] = ConfigFile( | |
'/etc/nginx/sites-available/my.domain.com', | |
""" | |
Server { | |
... | |
} | |
""" | |
) | |
files['uwsgi.app'] = ConfigFile( | |
'/etc/uwsgi/apps-available/my.domain.com.imi', | |
""" | |
[uwsgi] | |
plugins = python3 | |
... | |
""" | |
) | |
############################################################################### | |
# | |
# Simple demonstration | |
# | |
if __name__ == '__main__': | |
a = ConfigFile( | |
"demo.conf", | |
"pants {{pants}} pants", | |
"www-data" | |
) | |
# Print current state | |
print(a) | |
# Do something to it | |
a.replace('{{pants}}', '=') | |
a.content = "[pants]\n" + a.content | |
a.owner = os.getlogin() | |
a.group = os.getlogin() | |
a.name = "pants.ini" | |
print(a) | |
# Write to disk | |
a.create(overwrite = True) | |
# Remove it | |
os.remove(a.name) | |
# EOF |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment