from __future__ import absolute_import
from . import view
from . import model
from .constants import error as ERR
from mylinux.libs import AppErr
try:
input = raw_input
except NameError:
input = input
[docs]class Controller(object):
"""Main MVC controller of the package.
Args:
filesPath (str): Path to the file where main data is located.
Attributes:
_Controller__inited (boo): If False class was not inited yet.
Files (ins): Files instance.
Raises:
AppErr.developer: If singletone was allready inited.
Note:
This class is singletone which checks ``__inited``,
if instance was allready created.
"""
__inited = False
def __init__(self, filesPath):
if not Controller.__inited:
Controller.__inited = True
self.Files = model.Files(mainPath=filesPath)
else:
raise AppErr.developer(ERR.singletone)
[docs] def execute(self, ACTION, CONFIG=False, PACKAGE_NAMES=None):
"""Executing actions on packages.
Args:
ACTION (str): Execute action on packages.
CONFIG (boo): If action will be made on package config too.
PACKAGE_NAMES (arr-str): Name of package folder.
Other Parameters:
Start TUI if you want to select packages.
Create checks if action is allowed for all selected packages.
Execute action on packages.
Make report of executing.
"""
if not PACKAGE_NAMES:
PACKAGE_NAMES = self.__tuiSelect(ACTION, CONFIG)
if not PACKAGE_NAMES:
return
self.__postSelectCheck(ACTION, CONFIG, PACKAGE_NAMES)
self.__executeSelected(PACKAGE_NAMES)
self.__postExecuteReport(PACKAGE_NAMES)
[docs] def create(self, PACKAGE_NAME):
"""Guide to create new package.
Args:
PACKAGE_NAME (str): Package to be created.
Other Parameters:
Get existing packages.
Check if candidate already exist.
Start TUI for input package info.
Make file structure for package.
"""
existingPackages = self.Files.getPackageNames()
if PACKAGE_NAME in existingPackages:
view.Tli.raiseError(
AppErr.user,
'Create package',
['FAIL', PACKAGE_NAME, ERR.Format.alreadyExistIn('packages')]
)
else:
returned = self.__tuiCreate(PACKAGE_NAME)
self.Files.createPackage(
name=PACKAGE_NAME,
info=returned['info'],
scripts=returned['scripts']
)
[docs] def logs(self, PACKAGE_NAME):
"""Show logs
Args:
PACKAGE_NAME (str): Package name
Other Parameters:
Start TUI for logs
"""
self.__tuiLogs(PACKAGE_NAME)
[docs] def script(self, SCRIPT_NAME):
"""Execute main mylinux scripts
Args:
SCRIPT_NAME (str): Name of the script that is located in base scripts folder
Other Parameters:
Get info from the script.
Execute script line by line.
Print report
"""
report = []
executor = model.linux.Executor()
script = self.Files.getScript(SCRIPT_NAME)
for i, cmdArray in enumerate(script.cmdArrays):
executor.cwd = self.Files.scriptsPath
passed, stdout, stderr = executor.execute(cmdArray)
if passed:
report.append(['PASS', ' '.join(cmdArray), stdout.split('\n')[0]])
for stdout_line in stdout.split('\n')[1:-1]:
report.append(['', 'PASS', stdout_line])
else:
report.append(['ERROR', ' '.join(cmdArray), stderr.split('\n')[0]])
for stdout_line in stderr.split('\n')[1:-1]:
report.append(['', 'ERROR', stdout_line])
view.Tli.printReport(
'"{}" script executing'.format(SCRIPT_NAME),
report,
['Status', 'Code', 'stdout||stderr']
)
[docs] def test(self):
"""Make tests on already installed packages.
Other Parameters:
Get installed packages.
Execute test script for each package.
Make report.
"""
report = []
packagesNames = self.Files.installed.getNames()
executor = model.linux.Executor()
for package in self.Files.getPackages(packagesNames):
executor.cwd = package.scriptsPath
passed, stdout, stderr = executor.executeArrays(
[
['python', package.getScript('test.py').path]
]
)
if passed:
passed = 'PASS'
else:
passed = 'ERROR'
report.append([passed, package.name, stderr])
view.Tli.printReport(
'Installed packages',
report,
['Status', 'Package', 'stderr']
)
[docs] def check(self):
"""Check for errors for installed packages.
Other Parameters:
Check config/package state for every installed package.
Make report.
"""
report = []
for packageName in self.Files.installed():
configState = self.Files.installed[packageName]['configState']
packageState = self.Files.installed[packageName]['packageState']
state = 'OK'
if configState != 'ok' or packageState != 'ok':
if configState == 'error' or packageState == 'error':
state = 'ERROR'
else:
state = 'WARNING'
report.append([state, packageName, packageState, configState])
view.Tli.printReport('Installed packages check', report,
headers=['Status', 'Package', 'packageState', 'configState'])
def __tuiSelect(self, ACTION, CONFIG):
"""Start TUI for selecting packages.
Args:
ACTION (str): Joust for user visualization in TUI.
CONFIG (str): Joust for user vis. in TUI
Return:
Arr-str of selected packages names.
Other Parameters:
Get packages base on action and config.
Start TUI for selecting packages.
"""
# Basic filtering for qui view
if ACTION != 'install':
packages = self.Files.getPackages(self.Files.installed())
else:
packages = self.Files.packages
returnedValues = view.Tui.runSelectApp(
modelValues={
'action': ACTION,
'packages': packages,
'modules': self.Files.getModules(),
'classes': self.Files.getClasses(),
'packageNames': self.Files.getPackageNames(),
'packageInfos': self.Files.getInfoValues(),
'packageStates': self.Files.installed.getStates(
packageNames=self.Files.getPackageNames(),
key='packageState',
filler=''
),
'configStates': self.Files.installed.getStates(
packageNames=self.Files.getPackageNames(),
key='configState',
filler=''
)
}
)
return returnedValues['packageNames']
def __postSelectCheck(self, ACTION, CONFIG, PACKAGE_NAMES):
"""Post check after selection.
Args:
ACTION (str): Action that were executed.
CONFIG (boo): Were action done ono config too?
PACKAGE_NAMES (arr-str): Action were done on these packages.
Other Parameters:
Check existance of packages in package folder.
Check existance in installed and permissions of executing action.
If checks fails show user error report.
Override selected package installed flags for them to be executed.
"""
error = []
# Check existance in packages
for packageName in PACKAGE_NAMES:
if not packageName in self.Files.getPackageNames():
error = ['FAIL', packageName, ERR.Format.notExistIn('packages')]
# check existance in installed and permission to be updated/created...
self.Files.installed.createOrUpdateSelected(
config=CONFIG,
action=ACTION,
packageNames=PACKAGE_NAMES
)
if error:
view.Tli.raiseError(
AppErr.user,
'Post select check',
['FAIL', packageName, ERR.Format.alreadyExistIn('installed')],
headers=['Status', 'Package', 'Message']
)
else:
self.Files.installed.override()
def __executeSelected(self, PACKAGE_NAMES):
"""Execute selected packages
Args:
PACKAGE_NAMES (arg-str): Execute selected package names.
Other Parameters:
Make execute decisions for packages.
Execute package scripts with executor.
Update package info data in installed.
Override installed data.
If user want to exit wait for data to be writen.
If user wants really to exit raise user error.
"""
executor = model.linux.Executor()
packages = self.Files.getPackages(PACKAGE_NAMES)
executor.status['count_all'] = len(PACKAGE_NAMES)
for packageCount, package in enumerate(packages):
executor.cwd = package.scriptsPath
executor.status['name'] = package.name
executor.status['count'] = packageCount + 1
decision = self.Files.installed.decidePackageExecution(package.name)
# Required to be filled...
pass_package = None
stdout_package = ''
stderr_package = ''
pass_config = None
stdout_config = ''
stderr_config = ''
# Executing for decisions
if decision == 'installAll':
pass_package, stdout_package, stderr_package = executor.executeArrays(
cmdArrays=package.getScript('package-install').cmdArrays
)
if pass_package:
pass_config, stdout_config, stderr_config = executor.executeArrays(
cmdArrays=package.getScript('config-install').cmdArrays
)
elif decision == 'purgeAll':
pass_package, stdout_package, stderr_package = executor.executeArrays(
cmdArrays=package.getScript('package-purge').cmdArrays
)
if pass_package:
pass_config, stdout_config, stderr_config = executor.executeArrays(
cmdArrays=package.getScript('config-purge').cmdArrays
)
elif decision == 'installConfig':
pass_config, stdout_config, stderr_config = executor.executeArrays(
cmdArrays=package.getScript('config-install').cmdArrays
)
elif decision == 'purgeConfig':
pass_config, stdout_config, stderr_config = executor.executeArrays(
cmdArrays=package.getScript('config-purge').cmdArrays
)
elif decision == 'updateConfig':
pass_config, stdout_config, stderr_config = executor.executeArrays(
cmdArrays=package.getScript('config-purge').cmdArrays
)
if pass_config:
pass_config, stdout_install, stderr_install = executor.executeArrays(
cmdArrays=package.getScript('config-install').cmdArrays
)
stdout_config += stdout_install
stderr_config += stderr_install
self.Files.installed.packageAfterExecution(
packageName=package.name,
stdout=stdout_package + stdout_config,
stderr=stderr_package + stderr_config,
err_package=not pass_package if pass_package != None else None,
err_config=not pass_config if pass_config != None else None
)
# Override the installed file
self.Files.installed.override()
#Todo: Add msg to the constants
if executor.exit:
exit = input('>>> Really want to exit? [y/*]: ')
if exit == 'y':
raise AppErr.user('Exit on user request...')
def __postExecuteReport(self, PACKAGE_NAMES):
"""Post execute report for packages
Args:
PACKAGE_NAMES (arg-str): Package names to be subject of reporting.
Other Parameters:
Get packages states.
Report all packages states and if they pass
"""
report = []
for packageName in PACKAGE_NAMES:
packageState = self.Files.installed[packageName]['packageState']
configState = self.Files.installed[packageName]['configState']
if (packageState in ['ok','None']) and (configState in ['ok','None']):
passed = 'PASS'
else:
passed = 'ERROR'
report.append([
passed,
packageName,
packageState,
configState,
self.Files.installed[packageName]['stderr']
])
view.Tli.printReport(
'Execution status',
report,
headers=['Status', 'Package name', 'Package', 'Config', 'stderr']
)
def __tuiCreate(self, PACKAGE_NAME):
"""Start TUI for package creation.
Args:
PACKAGE_NAME (str): Package to be created.
Return:
Dic object similar to argument ``modelValues``.
For more info see source.
Other Parameters:
Start TUI for creation.
Return all info obout the new package.
"""
returnedValues = view.Tui.runCreateApp(
modelValues={
'packageName': PACKAGE_NAME,
'hints': {
'moduleName': self.Files.getModules(),
'className': self.Files.getClasses()
},
'package-install': [
'sudo apt-get install {0}'.format(PACKAGE_NAME)
],
'package-purge': [
'sudo apt-get purge {0}'.format(PACKAGE_NAME)
],
'config-install': [
'sudo mv {0} {1}'.format(
self.Files.packagesPath + '/' + PACKAGE_NAME + '/data/*',
'~/.' + PACKAGE_NAME + 'rc'
)
],
'config-purge': [
'sudo rm -rf {0}'.format('~/.' + PACKAGE_NAME + 'rc')
],
'test.py': [
'import os',
'#Test config existance',
'os.path.exists()',
'#Test package installation',
'os.call("{0} --version")'.format(PACKAGE_NAME)
]
}
)
return returnedValues
def __tuiLogs(self, PACKAGE_NAME):
"""Start TUI for package log.
Args:
PACKAGE_NAME (str): Name of the installed package.
Other Parameters:
Get ``stderr`` and ``stdout`` info from package in installed.
Start logs TUI.
"""
view.Tui.runLogsApp(
modelValues={
'packageName': PACKAGE_NAME,
'stdout': self.Files.installed[PACKAGE_NAME]['stdout'].split('\n'),
'stderr': self.Files.installed[PACKAGE_NAME]['stderr'].split('\n')
}
)