Added a postgresql application profile. (#383)

* Added a postgres application profile. Also introducing runas to the arch_chroot of the installation, to run commands as emulated users. This is highly WIP at the moment.

* Fixing top-level-listing of profiles. As well as testing some postgres installation steps.

* Removed dupe functions.

* Added safety check in case a comment mentions the top level profile thing.

* Patching namespace corruption.

* Avoiding runtime collision due to installation not being initiated yet.

* Allow for parameterization of filesystem in guided.

Co-authored-by: Anton Hvornum <anton.feeds@gmail.com>
This commit is contained in:
Anton Hvornum 2021-04-29 11:32:21 +00:00 committed by GitHub
parent aa0f432726
commit 0ebc6be7ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 36 additions and 50 deletions

View File

@ -471,7 +471,6 @@ class Filesystem():
def raw_parted(self, string:str):
x = sys_command(f'/usr/bin/parted -s {string}')
log(f"'parted -s {string}' returned: {b''.join(x)}", level=logging.DEBUG)
return x
def parted(self, string:str):

View File

@ -196,6 +196,9 @@ class Installer():
return sys_command(f'/usr/bin/arch-chroot {self.target} {cmd}')
def arch_chroot(self, cmd, *args, **kwargs):
if 'runas' in kwargs:
cmd = f"su - {kwargs['runas']} -c \"{cmd}\""
return self.run_command(cmd)
def drop_to_shell(self):

View File

@ -92,6 +92,9 @@ class Script():
if len(args) >= 2 and args[1]:
raise args[1]
if self.original_namespace:
self.namespace = self.original_namespace
def localize_path(self, profile_path):
if (url := urllib.parse.urlparse(profile_path)).scheme and url.scheme in ('https', 'http'):
if not self.converted_path:
@ -202,8 +205,14 @@ class Profile(Script):
with open(self.path, 'r') as source:
source_data = source.read()
# TODO: I imagine that there is probably a better way to write this.
return 'top_level_profile = True' in source_data
if '__name__' in source_data and 'is_top_level_profile' in source_data:
with self.load_instructions(namespace=f"{self.namespace}.py") as imported:
if hasattr(imported, 'is_top_level_profile'):
return imported.is_top_level_profile
# Default to True if nothing is specified,
# since developers like less code - omitting it should assume they want to present it.
return True
@property
def packages(self) -> list:
@ -225,50 +234,6 @@ class Profile(Script):
if hasattr(imported, '__packages__'):
return imported.__packages__
return None
def has_post_install(self):
with open(self.path, 'r') as source:
source_data = source.read()
# Some crude safety checks, make sure the imported profile has
# a __name__ check and if so, check if it's got a _prep_function()
# we can call to ask for more user input.
#
# If the requirements are met, import with .py in the namespace to not
# trigger a traditional:
# if __name__ == 'moduleName'
if '__name__' in source_data and '_post_install' in source_data:
with self.load_instructions(namespace=f"{self.namespace}.py") as imported:
if hasattr(imported, '_post_install'):
return True
def is_top_level_profile(self):
with open(self.path, 'r') as source:
source_data = source.read()
return 'top_level_profile = True' in source_data
@property
def packages(self) -> list:
"""
Returns a list of packages baked into the profile definition.
If no package definition has been done, .packages() will return None.
"""
with open(self.path, 'r') as source:
source_data = source.read()
# Some crude safety checks, make sure the imported profile has
# a __name__ check before importing.
#
# If the requirements are met, import with .py in the namespace to not
# trigger a traditional:
# if __name__ == 'moduleName'
if '__name__' in source_data and '__packages__' in source_data:
with self.load_instructions(namespace=f"{self.namespace}.py") as imported:
if hasattr(imported, '__packages__'):
return imported.__packages__
return None
class Application(Profile):
def __repr__(self, *args, **kwargs):

View File

@ -136,12 +136,14 @@ def ask_user_questions():
archinstall.log('Using existing partition table reported above.')
elif option == 'format-all':
archinstall.arguments['filesystem'] = archinstall.ask_for_main_filesystem_format()
if not archinstall.arguments.get('filesystem', None):
archinstall.arguments['filesystem'] = archinstall.ask_for_main_filesystem_format()
archinstall.arguments['harddrive'].keep_partitions = False
elif archinstall.arguments['harddrive']:
# If the drive doesn't have any partitions, safely mark the disk with keep_partitions = False
# and ask the user for a root filesystem.
archinstall.arguments['filesystem'] = archinstall.ask_for_main_filesystem_format()
if not archinstall.arguments.get('filesystem', None):
archinstall.arguments['filesystem'] = archinstall.ask_for_main_filesystem_format()
archinstall.arguments['harddrive'].keep_partitions = False
# Get disk encryption password (or skip if blank)

View File

@ -4,6 +4,11 @@ import urllib.request
__packages__ = ['nano', 'wget', 'git']
if __name__ == '52-54-00-12-34-56':
awesome = archinstall.Application(installation, 'postgresql')
awesome.install()
"""
# Unmount and close previous runs (Mainly only used for re-runs, but won't hurt.)
archinstall.sys_command(f'umount -R /mnt', suppress_errors=True)
archinstall.sys_command(f'cryptsetup close /dev/mapper/luksloop', suppress_errors=True)
@ -51,4 +56,5 @@ with archinstall.Filesystem(harddrive) as fs:
try:
urllib.request.urlopen(req, timeout=5)
except:
pass
pass
"""

View File

@ -0,0 +1,11 @@
import archinstall
# Define the package list in order for lib to source
# which packages will be installed by this profile
__packages__ = ["postgresql"]
installation.add_additional_packages(__packages__)
installation.arch_chroot("initdb -D /var/lib/postgres/data", runas='postgres')
installation.enable_service('postgresql')