Skip to content

Instantly share code, notes, and snippets.

@Jasata
Last active December 17, 2019 14:40
Show Gist options
  • Save Jasata/8b7cb4a190ea47902df1bed8b8552476 to your computer and use it in GitHub Desktop.
Save Jasata/8b7cb4a190ea47902df1bed8b8552476 to your computer and use it in GitHub Desktop.
Python class for configuration files (installation scripts run by root)
#! /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