Exemple #1
0
def run_command(self, cmd, spinner=True, quiet=True):
    '''run_command will run a command (a list) and wrap in a spinner. A 
       result (dict) with message and return code is returned. If the
       return value is not 0, an error is issed and we exit
    '''
    if spinner is True:
        bot.spinner.start()

    result = run_cmd(cmd)

    if spinner is True:
        bot.spinner.stop()

    retval = result['return_code']

    if quiet is False:
        if isinstance(result['message'], bytes):
            result['message'] = result['message'].decode('utf-8')
        print(result['message'])

    # Beep boop, error!
    if retval != 0:
        bot.error('Return code %s' % retval)
        sys.exit(retval)

    return result
Exemple #2
0
def set_base(self, base='/', writable=True):
    ''' set the base (the root where to create /scif) and determine if
        it is writable

        Parameters
        ==========
        base: the full path to the root folder to create /scif
    '''
    # The user is likely to give path to scif (should still work)
    base = base.strip('scif')

    if not os.path.exists(base):
        bot.error('%s does not exist!' % base)
        sys.exit(1)

    base = "/%s" % os.path.abspath(base).strip('/')
    self._base = os.path.join(base, 'scif')
    self.path_apps = '%s/apps' % self._base
    self.path_data = '%s/data' % self._base

    # Update the environment
    self.add_env('SCIF_DATA', self.path_data)
    self.add_env('SCIF_APPS', self.path_apps)

    # Check if it's writable
    if writable is True:
        if not os.access(base, os.W_OK):
            bot.error('%s is not writable.' % base)
            sys.exit(1)
Exemple #3
0
def preview_apps(self, apps=None):
    '''install one or more apps to the base. If app is defined, only
       install app specified. Otherwise, install all found in config.
    '''
    if apps in [None, []]:
        apps = self.apps()

    if not isinstance(apps, list):
        apps = [apps]

    for app in apps:

        # We must have the app defined in the config
        if app not in self._config['apps']:
            bot.error('Cannot find app %s in config.' % app)
            sys.exit(1)

        # Make directories
        bot.newline()
        settings = self._init_app_preview(app)

        # Get the app configuration
        config = self.app(app)

        # Handle environment, runscript, labels
        self._preview_runscript(app, settings, config)
        self._preview_environment(app, settings, config)
        self._preview_labels(app, settings, config)
        self._preview_commands(app, settings, config)
        self._preview_files(app, settings, config)
        self._preview_recipe(app, settings, config)
        self._preview_test(app, settings, config)
        bot.newline()
Exemple #4
0
def mkdir_p(path):
    '''mkdir_p attempts to get the same functionality as mkdir -p
    :param path: the path to create.
    '''
    try:
        os.makedirs(path)
    except OSError as e:
        if e.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            bot.error("Error creating path %s, exiting." % path)
            sys.exit(1)
Exemple #5
0
def preview_base(self):
    ''' preview basic scif structure at the base for apps and metadata

        Parameters
        ==========
        base: the full path to the root folder to create /scif
    '''
    if not hasattr(self, '_base'):
        bot.error('Please set the base before preview.')
        sys.exit(1)

    bot.custom(prefix='[base] %s' % self._base, color='CYAN')
    bot.custom(prefix='[apps] %s' % self.path_apps, color='CYAN')
    bot.custom(prefix='[data] %s\n' % self.path_data, color='CYAN')
Exemple #6
0
def install_base(self):
    ''' create basic scif structure at the base for apps and metadata

        Parameters
        ==========
        base: the full path to the root folder to create /scif
    '''
    if not hasattr(self, '_base'):
        bot.error('Please set the base before installing to it.')
        sys.exit(1)

    bot.info('Installing base at %s' % self._base)

    mkdir_p(self.path_apps)
    mkdir_p(self.path_data)
Exemple #7
0
def get_appenv(self, app, isolated=True, update=False):
    '''return environment for a specific app, meaning the variables active
       when it is running. 

       Parameters
       ==========
       isolated: if True, only return the active app variables (example  below)
       update: also update the global self.environment.

       If isolated is True, don't include other apps. For
       example, for an app `hello-world-echo` and isolated True, the following
       is returned:

       {
           'SCIF_APPBIN': '/scif/apps/hello-world-echo/bin',
           'SCIF_APPDATA': '/scif/data/hello-world-echo',
           'SCIF_APPENV': '/scif/apps/hello-world-echo/scif/environment.sh',
           'SCIF_APPHELP': '/scif/apps/hello-world-echo/scif/runscript.help',
           'SCIF_APPLABELS': '/scif/apps/hello-world-echo/scif/labels.json',
           'SCIF_APPLIB': '/scif/apps/hello-world-echo/lib',
           'SCIF_APPMETA': '/scif/apps/hello-world-echo/scif',
           'SCIF_APPNAME': 'hello-world-echo',
           'SCIF_APPRECIPE': '/scif/apps/hello-world-echo/scif/hello-world-echo.scif',
           'SCIF_APPROOT': '/scif/apps/hello-world-echo',
           'SCIF_APPRUN': '/scif/apps/hello-world-echo/scif/runscript'
           'SCIF_APPTEST': '/scif/apps/hello-world-echo/scif/test.sh'
       }

    '''
    final = dict()
    if app in self.apps():
        environ = self.get_appenv_lookup(app)
        for var, val in environ[app].items():
            updates = mk_env(key=var, val=val)
            final.update(updates)

        # The user wants to include the current SCIF environment
        if isolated is False and hasattr(self,'environment'):
            final.update(self.environment)

        # The user also wants to update the SCIF environment
        if update is True:
            self.environment = final
        
        return final

    valid = ' '.join(self.apps())
    bot.error('%s is not a valid app. Found %s' %(app, valid))
Exemple #8
0
def main(args, parser, subparser):

    from scif.main import ScifRecipe
    apps = args.recipe

    if len(apps) > 0:
        recipe = apps.pop(0)

        if not os.path.exists(recipe):
            bot.error("Cannot find recipe file %s" % recipe)
            sys.exit(1)

        client = ScifRecipe(recipe, writable=False)

        # Preview the entire recipe, or the apps chosen
        client.preview(apps)

    else:
        bot.info('You must provide a recipe file to preview!')
Exemple #9
0
def getenv(variable_key, default=None, required=False, silent=True):
    '''
    getenv will attempt to get an environment variable. If the variable
    is not found, None is returned.

    :param variable_key: the variable name
    :param required: exit with error if not found
    :param silent: Do not print debugging information for variable
    '''
    variable = os.environ.get(variable_key, default)
    if variable is None and required:
        bot.error("Cannot find environment variable %s, exiting." %
                  variable_key)
        sys.exit(1)

    if not silent and variable is not None:
        bot.verbose("%s found as %s" % (variable_key, variable))

    return variable
Exemple #10
0
def run_command(self, cmd, spinner=True):
    '''run_install will run a command (a list) and wrap in a spinner. A 
       result (dict) with message and return code is returned. If the
       return value is not 0, an error is issed and we exit
    '''
    if spinner is True:
        bot.spinner.start()

    result = run_cmd(cmd)

    if spinner is True:
        bot.spinner.stop()

    retval = result['return_code']
    bot.info(result['message'])
    if retval != 0:
        bot.error('Return code %s' % retval)
        sys.exit(retval)
    return result
Exemple #11
0
def install_apps(self, apps=None):
    '''install one or more apps to the base. If app is defined, only
       install app specified. Otherwise, install all found in config.
    '''
    if apps in [None, '']:
        apps = self.apps()

    if not isinstance(apps, list):
        apps = [apps]

    if len(apps) == 0:
        bot.warning('No apps to install. Load a recipe or base with .load()')

    for app in apps:

        # We must have the app defined in the config
        if app not in self._config['apps']:
            bot.error('Cannot find app %s in config.' %app)
            sys.exit(1)

        # Make directories
        settings = self._init_app(app)

        # Get the app configuration
        config = self.app(app)

        # Get the app environment and export for install
        self.get_appenv(app, isolated=False, update=True)
        self.export_env(ps1=False)

        # Handle environment, runscript, labels
        self._install_runscript(app, settings, config)
        self._install_environment(app, settings, config)
        self._install_help(app, settings, config)
        self._install_labels(app, settings, config)
        self._install_files(app, settings, config)
        self._install_commands(app, settings, config)
        self._install_recipe(app, settings, config)
        self._install_test(app, settings, config)

        # After we install, in case interactive, deactivate last app
        self.deactivate(app)
Exemple #12
0
def add_section(config, section, name=None):
    '''add section will add a section (and optionally)
    section name to a config

    Parameters
    ==========
    config: the config (dict) parsed thus far
    section: the section type (e.g., appinstall)
    name: an optional name, added as a level (e.g., google-drive)

    Resulting data structure is:

            config['registry']['apprun']
            config[name][section]

    '''

    if section is None:
        bot.error(
            'You must define a section (e.g. %appenv) before any action.')
        sys.exit(1)

    if section not in sections:
        bot.error("%s is not a valid section." % section)
        sys.exit(1)

    global_section = 'apps'

    # Add the global section, if doesn't exist
    if global_section not in config:
        config[global_section] = OrderedDict()

    if name is not None:
        if name not in config[global_section]:
            config[global_section][name] = OrderedDict()

        if section not in config[global_section][name]:
            config[global_section][name][section] = []
            bot.debug("Adding section %s %s" % (name, section))

    return config
Exemple #13
0
def main(args, parser, subparser):

    from scif.main import ScifRecipe
    apps = args.recipe

    if len(apps) == 0:
        bot.error("You must provide a recipe (.scif) file to install.")
        sys.exit(1)

    recipe = apps.pop(0)

    if not os.path.exists(recipe):
        bot.error("Cannot find recipe file %s" % recipe)
        sys.exit(1)

    if len(apps) == 0:
        apps = None

    client = ScifRecipe(recipe)  # writable is True

    # Preview the entire recipe, or the apps chosen
    client.install(apps)
Exemple #14
0
def get_appenv_lookup(self, app):
    '''create a dictionary with a highest level index the
       app name, and underneath a generic lookup (without the app name) for
       different variable types.  

       Parameters
       ==========
       app: the new of the app to get the environment for
       isolated: if True don't include other apps

       Eg, app with name "google-drive" would look like:


       {'registry': {
                      'appbin': '/scif/apps/registry/bin',
                      'appdata': '/scif/data/registry',
                      'appenv': '/scif/apps/registry/scif/environment.sh',
                      'apphelp': '/scif/apps/registry/scif/runscript.help',
                      'apptest': '/scif/apps/registry/scif/test.sh',
                      'applabels': '/scif/apps/registry/scif/labels.json',
                      'applib': '/scif/apps/registry/lib',
                      'appmeta': '/scif/apps/registry/scif',
                      'apprecipe': '/scif/apps/registry/scif/registry.scif'
                      'approot': '/scif/apps/registry',
                      'apprun': '/scif/apps/registry/scif/runscript'
                    }            
       }

       This function is intended to be shared by env above and the environment
       generating functions in the main client, to have consistent behavior. 
       The above data structure gets parse into the (global) variables for
       the particular app:

       {'SCIF_APPBIN_registry': '/scif/apps/registry/bin',
        'SCIF_APPDATA_registry': '/scif/data/registry',
        'SCIF_APPENV_registry': '/scif/apps/registry/scif/environment.sh',
        'SCIF_APPHELP_registry': '/scif/apps/registry/scif/runscript.help',
        'SCIF_APPLABELS_registry': '/scif/apps/registry/scif/labels.json',
        'SCIF_APPTEST_registry': '/scif/apps/registry/scif/test.sh',
        'SCIF_APPLIB_registry': '/scif/apps/registry/lib',
        'SCIF_APPMETA_registry': '/scif/apps/registry/scif',
        'SCIF_APPRECIPE_registry': '/scif/apps/registry/scif/registry.scif',
        'SCIF_APPROOT_registry': '/scif/apps/registry',
        'SCIF_APPRUN_registry': '/scif/apps/registry/scif/runscript'}

    '''

    if app in self.apps():

        base = self._base
        envars = {app:{}}

        # Roots for app data and app files
        appdata = "%s/data/%s" %(base, app)
        approot = "%s/apps/%s" %(base, app)
        appmeta = "%s/scif"  %(approot)

        envars[app]['appdata'] = appdata
        envars[app]['approot'] = approot
        envars[app]['appmeta'] = appmeta

        envars[app]['appbin'] = "%s/bin"  %(approot)
        envars[app]['applib'] = "%s/lib"  %(approot)
        envars[app]['apprun'] = "%s/runscript"  %(appmeta)
        envars[app]['apphelp'] = "%s/runscript.help"  %(appmeta)
        envars[app]['appenv'] = "%s/environment.sh"  %(appmeta)
        envars[app]['apptest'] = "%s/test.sh"  %(appmeta)
        envars[app]['applabels'] = "%s/labels.json"  %(appmeta)
        envars[app]['apprecipe'] = "%s/%s.scif"  %(appmeta, app)
        envars[app]['appname'] = app
        return envars

    # if we get down here, didn't have the app in the first place
    valid = ' '.join(self.apps())
    bot.error('%s is not a valid app. Found %s' %(app, valid))