class Git(object): cli = simpcli.Command() verboseCli = simpcli.Command(True) config = GitcdConfig() configPersonal = GitcdPersonalConfig() def getConfig(self) -> GitcdConfig: return self.config def getPersonalConfig(self) -> GitcdPersonalConfig: return self.configPersonal
class BaseCommand(object): interface = simpcli.Interface() command = simpcli.Command(True) config = ManagerConfig() projects = Projects() runPerProject = True def __init__(self): self.config.load() className = self.__class__.__name__ if self.projects.getAll( ) == {} and className != 'Init' and className != 'ExtraCommand': self.interface.error('No projects found in your config') self.interface.writeOut( 'To add a project navigate into a directory with a docker-compose.yml and execute docker-manager init.' ) self.exit() def getRunPerProject(self): return self.runPerProject def exit(self): sys.exit(1) def bold(self, string): self.interface.writeOut( '%s%s%s' % (self.interface.BOLD, string, self.interface.ENDC))
class Upgrade(App): localVersion = 0 pypiVersion = 0 packageUrl = 'https://pypi.org/pypi/gitcd/json' verboseCli = simpcli.Command(True) def getLocalVersion(self) -> str: self.localVersion = pkg_resources.get_distribution("gitcd").version return self.localVersion def getPypiVersion(self) -> str: response = requests.get(self.packageUrl) if response.status_code != 200: raise GitcdPyPiApiException( "Could not fetch version info on PyPi site." + "You need to check manually, sorry for that.") result = response.json() self.pypiVersion = result['info']['version'] return self.pypiVersion def isUpgradable(self) -> bool: if version.parse(self.localVersion) < version.parse(self.pypiVersion): return True return False def upgrade(self) -> bool: self.verboseCli.execute("pip3 install --user --upgrade gitcd") return True
def release(self, version: str, message: str, remote: Remote) -> bool: tag = Tag(version) tag.create(message) remote.push(tag) extraCommand = self.config.getExtraReleaseCommand() if extraCommand is not None: cli = simpcli.Command(True) cli.execute(extraCommand) return True
def readGitCdFolders(self): cli = simpcli.Command() result = cli.execute('find ~ -path "*/.gitcd" 2>/dev/null', True) folders = result.split("\n") gitFolders = [] for folder in folders: folder = folder.replace('/.gitcd', '') folderParts = folder.split('/') gitFolder = {'name': folderParts[-1], 'path': folder} gitFolders.append(gitFolder) return gitFolders
class BasicAuth(BasePlugin): cli = simpcli.Command() basePath = '/etc/nginx/basic_auth.d' def write(self): if os.path.isfile("%s/%s" % (self.basePath, self.name)): print("Password for %s already set" % (self.name)) return False if 'password' in self.settings['nginx'] and self.settings['nginx'][ 'password'] == '<pwgen>': pw = self.cli.execute( "pwgen --capitalize --numerals --symbols -1 32 1") elif 'password' in self.settings['nginx']: pw = self.settings['nginx']['password'] else: return False self.cli.execute( "printf \"%s:$(openssl passwd -crypt '%s')\" > %s/%s" % (self.name, pw, self.basePath, self.name)) print("%s:%s" % (self.name, pw)) return True def remove(self): if os.path.isfile("%s/%s" % (self.basePath, self.name)): self.cli.execute("rm %s/%s" % (self.basePath, self.name)) # callable methods def start(self): # should optimize and do that only on creation of the container #self.write() print('start basic auth plugin') pass def destroy(self): #self.remove() print('destroy basic auth plugin') pass
def reload(self): command = simpcli.Command() command.execute("service nginx reload")
class Cli(): interface = simpcli.Interface() command = simpcli.Command(True) projects = Projects() plugins = [] commands = [ "status", "start", "stop", "update", "restart", "destroy", "init", "deinit", "projects", "pull", "cd" ] commandsNotRunningByProjects = ['init', 'deinit', 'projects'] def getAvailableCommands(self): return self.commands def instantiateCommand(self, command: str) -> BaseCommand: if command == 'status': return StatusCommand() if command == 'start': return StartCommand() if command == 'stop': return StopCommand() if command == 'update': return UpdateCommand() if command == 'restart': return RestartCommand() if command == 'destroy': return DestroyCommand() if command == 'init': return InitCommand() if command == 'deinit': return DeinitCommand() if command == 'projects': return ProjectsCommand() if command == 'pull': return PullCommand() if command == 'cd': return ChangeDirectoryCommand() raise CommandNotFoundException('Command "%s" not found!' % (command)) def bold(self, string): self.interface.writeOut( '%s%s%s' % (self.interface.BOLD, string, self.interface.ENDC)) def dispatch(self, command: str, project: str, service: str): projects = [] if project == 'all-projects': for project in self.projects.getAll(): projects.append(project) else: projects.append(project) self.interface.header('docker-manager %s' % (command)) extraCommandObject = ExtraCommand(command) if command in self.commandsNotRunningByProjects: self.runCommand(command, project, service) else: for project in projects: self.interface.writeOut('') self.bold(project) self.runCommand(command, project, service) def runCommand(self, command: str, project: str, service: str): project = self.projects.getProject(project) extraCommandObject = ExtraCommand(command) try: commandObject = self.instantiateCommand(command) except CommandNotFoundException: # if default command fails, try to find some extra commands try: extraCommandObject.run(project, service) except NoExtraCommandFoundException: # if not even an extraCommand is found, output an error errorMessage = 'Neither a command nor an extraCommand with the name "%s" was found in project "%s".' self.interface.error(errorMessage % (command, project)) pass try: commandObject.run(project, service) self.runPlugins(command, project) try: # try running additional commands stored in projects extraCommandObject.run(project, service) except NoExtraCommandFoundException: pass # catch cli execution errors here except UnboundLocalError: pass except Exception as e: errorMessage = 'An error occured\n' + \ ' Exception was: %s' self.interface.error(errorMessage % (e)) self.interface.error(format(e)) def runPlugins(self, command, project): try: self.plugins = [ # BasicAuth(), # Nginx(), Hosts() ] project.changeWorkingDirectory() compose = Compose() for plugin in self.plugins: if not hasattr(plugin, command): continue self.interface.writeOut('') self.interface.info('Running %s' % (plugin.name)) for container in compose.getContainers(): success, message = plugin.run(command, container) if message: self.interface.writeOut(message) except Exception as e: self.interface.error('Plugin Exception') self.interface.writeOut(e) self.interface.writeOut(traceback.format_exc()) def close(self, msg: str): self.interface.ok(msg)
class Kivy(App): currentDirectory = StringProperty() cli = simpcli.Command() theme_cls = ThemeManager() theme_cls.theme_style = 'Dark' theme_cls.primary_palette = 'LightGreen' theme_cls.accent_palette = 'Orange' def setCurrentDirectory(self, directory: str): if not os.path.exists(directory): # error dialog maybe? return False self.currentDirectory = directory os.chdir(self.currentDirectory) def getCurrentRepository(self): return self.currentRepository def build(self): return Builder.load_string(""" #:import NavigationLayout kivymd.navigationdrawer.NavigationLayout #:import MDThemePicker kivymd.theme_picker.MDThemePicker #:import GitcdUpgradeDialog gitcd.interface.kivy.upgrade.GitcdUpgradeDialog #:import GitcdCleanDialog gitcd.interface.kivy.clean.GitcdCleanDialog #:import GitcdNavigationDrawer gitcd.interface.kivy.navigation.GitcdNavigationDrawer #:import GitcdBranchPanel gitcd.interface.kivy.branchpanel.GitcdBranchPanel #:import GitcdTagPanel gitcd.interface.kivy.tagpanel.GitcdTagPanel #:import GitcdInfoPanel gitcd.interface.kivy.infopanel.GitcdInfoPanel #:import GitcdMainPanel gitcd.interface.kivy.mainpanel.GitcdMainPanel NavigationLayout: id: nav_layout side_panel_width: dp(500) GitcdNavigationDrawer: id: nav_drawer BoxLayout: orientation: 'vertical' Toolbar: id: toolbar title: "You are currently in " + app.currentDirectory md_bg_color: app.theme_cls.primary_color background_palette: 'Primary' background_hue: '500' left_action_items: [['folder-outline', lambda x: app.root.toggle_nav_drawer()]] right_action_items: [['sync', lambda x: GitcdCleanDialog().open()], ['help', lambda x: GitcdUpgradeDialog().open()], ['format-color-fill', lambda x: MDThemePicker().open()]] BoxLayout: spacing: 20 padding: [20, 20, 20, 20] GitcdMainPanel: id: main_panel # GitcdBranchPanel: # id: branch_panel # MDSeparator: # width: dp(1) # GitcdTagPanel: # id: tag_panel # MDSeparator: # width: dp(1) # GitcdInfoPanel: # id: info_panel """)