Beispiel #1
0
def test_find_by_env_var_unknown():
    registry = PluginRegistry()
    found = registry.find_requirement_by_env_var(env_var='FOO', options=None)
    assert found is not None
    assert isinstance(found, EnvVarRequirement)
    assert found.env_var == 'FOO'
    assert "EnvVarRequirement(env_var='FOO')" == repr(found)
def test_find_by_service_type_redis():
    registry = PluginRegistry()
    found = registry.find_requirement_by_service_type(service_type='redis', env_var='MYREDIS', options=dict())
    assert found is not None
    assert isinstance(found, RedisRequirement)
    assert found.env_var == 'MYREDIS'
    assert found.service_type == 'redis'
Beispiel #3
0
def test_empty_variable_treated_as_unset():
    requirement = EnvVarRequirement(registry=PluginRegistry(), env_var='FOO')
    status = requirement.check_status(dict(FOO=''), tmp_local_state_file(), 'default', UserConfigOverrides())
    assert not status
    assert "Environment variable FOO is not set." == status.status_description
    assert [] == status.logs
    assert [] == status.errors
 def check_not_set(dirname):
     local_state = LocalStateFile.load_for_directory(dirname)
     requirement = DownloadRequirement(registry=PluginRegistry(),
                                       env_var=ENV_VAR,
                                       url='http://example.com',
                                       filename=ENV_VAR)
     status = requirement.check_status(dict(PROJECT_DIR=dirname), local_state, 'default', UserConfigOverrides())
     assert not status
     assert "Environment variable {} is not set.".format(ENV_VAR) == status.status_description
 def check_bad_scheme(dirname):
     local_state = LocalStateFile.load_for_directory(dirname)
     requirement = RedisRequirement(registry=PluginRegistry(), env_var="REDIS_URL")
     status = requirement.check_status(
         dict(REDIS_URL="http://example.com/"),
         local_state,
         'default',
         UserConfigOverrides())
     assert not status
     assert "REDIS_URL value 'http://example.com/' does not have 'redis:' scheme." == status.status_description
 def check_missing_filename(dirname):
     local_state = LocalStateFile.load_for_directory(dirname)
     filename = '/data.zip'
     requirement = DownloadRequirement(registry=PluginRegistry(),
                                       env_var=ENV_VAR,
                                       url='http://localhost/data.zip',
                                       filename='data.zip')
     status = requirement.check_status({ENV_VAR: filename,
                                        'PROJECT_DIR': dirname}, local_state, 'default', UserConfigOverrides())
     assert not status
     assert 'File not found: {}'.format(filename) == status.status_description
def test_description_is_not_a_string():
    problems = []
    requirements = []
    DownloadRequirement._parse(PluginRegistry(),
                               varname='FOO',
                               item=dict(url='http://example.com/',
                                         description=[]),
                               problems=problems,
                               requirements=requirements)
    assert ["'description' field for download item FOO is not a string"] == problems
    assert len(requirements) == 0
def test_unzip_is_not_a_bool():
    problems = []
    requirements = []
    DownloadRequirement._parse(PluginRegistry(),
                               varname='FOO',
                               item=dict(url='http://example.com/',
                                         unzip=[]),
                               problems=problems,
                               requirements=requirements)
    assert ["Value of 'unzip' for download item FOO should be a boolean, not []."] == problems
    assert len(requirements) == 0
def test_checksum_is_not_a_string():
    problems = []
    requirements = []
    DownloadRequirement._parse(PluginRegistry(),
                               varname='FOO',
                               item=dict(url='http://example.com/',
                                         md5=[]),
                               problems=problems,
                               requirements=requirements)
    assert ['Checksum value for FOO should be a string not [].'] == problems
    assert len(requirements) == 0
Beispiel #10
0
 def check_missing_package(dirname):
     requirement = CondaEnvRequirement(
         registry=PluginRegistry(),
         env_specs=dict(default=EnvSpec(
             'default', ['boguspackage', 'boguspackage2'], [])))
     project_dir_disable_dedicated_env(dirname)
     local_state = LocalStateFile.load_for_directory(dirname)
     environ = minimal_environ(PROJECT_DIR=dirname)
     status = requirement.check_status(
         environ, local_state, 'default',
         UserConfigOverrides(inherited_env=environ.get(conda_env_var)))
     assert "Conda environment is missing packages: boguspackage, boguspackage2" == status.status_description
Beispiel #11
0
 def check_provide_contents(dirname):
     environ = dict(foo='bar')
     local_state_file = LocalStateFile.load_for_directory(dirname)
     requirement = EnvVarRequirement(PluginRegistry(), env_var="FOO")
     status = requirement.check_status(environ, local_state_file, 'default', UserConfigOverrides())
     context = ProvideContext(environ=environ,
                              local_state_file=local_state_file,
                              default_env_spec_name='default',
                              status=status,
                              mode=PROVIDE_MODE_DEVELOPMENT)
     assert dict(foo='bar') == context.environ
     assert context.status is status
def test_description_property():
    problems = []
    requirements = []
    DownloadRequirement._parse(PluginRegistry(),
                               varname='FOO',
                               item=dict(url='http://example.com/',
                                         description="hi"),
                               problems=problems,
                               requirements=requirements)
    assert [] == problems
    assert len(requirements) == 1
    assert requirements[0].title == 'FOO'
    assert requirements[0].description == 'hi'
def test_use_unzip_if_url_ends_in_zip():
    problems = []
    requirements = []
    DownloadRequirement._parse(PluginRegistry(),
                               varname='FOO',
                               item='http://example.com/bar.zip',
                               problems=problems,
                               requirements=requirements)
    assert [] == problems
    assert len(requirements) == 1
    assert requirements[0].filename == 'bar'
    assert requirements[0].url == 'http://example.com/bar.zip'
    assert requirements[0].unzip
Beispiel #14
0
 def check_provide_contents(dirname):
     environ = dict()
     local_state_file = LocalStateFile.load_for_directory(dirname)
     requirement = EnvVarRequirement(PluginRegistry(), env_var="FOO")
     status = requirement.check_status(environ, local_state_file, 'default', UserConfigOverrides())
     context = ProvideContext(environ=environ,
                              local_state_file=local_state_file,
                              default_env_spec_name='default',
                              status=status,
                              mode=PROVIDE_MODE_DEVELOPMENT)
     with pytest.raises(IOError) as excinfo:
         context.ensure_service_directory("foo")
     assert "this is not EEXIST" in repr(excinfo.value)
def test_allow_manual_override_of_use_unzip_if_url_ends_in_zip():
    problems = []
    requirements = []
    DownloadRequirement._parse(PluginRegistry(),
                               varname='FOO',
                               item=dict(url='http://example.com/bar.zip',
                                         unzip=False),
                               problems=problems,
                               requirements=requirements)
    assert [] == problems
    assert len(requirements) == 1
    assert requirements[0].filename == 'bar.zip'
    assert requirements[0].url == 'http://example.com/bar.zip'
    assert not requirements[0].unzip
def test_no_unzip_if_url_ends_in_zip_and_filename_also_does():
    problems = []
    requirements = []
    DownloadRequirement._parse(PluginRegistry(),
                               varname='FOO',
                               item=dict(url='http://example.com/bar.zip',
                                         filename='something.zip'),
                               problems=problems,
                               requirements=requirements)
    assert [] == problems
    assert len(requirements) == 1
    assert requirements[0].filename == 'something.zip'
    assert requirements[0].url == 'http://example.com/bar.zip'
    assert not requirements[0].unzip
    def check_cannot_connect(dirname):
        local_state = LocalStateFile.load_for_directory(dirname)
        requirement = RedisRequirement(registry=PluginRegistry(), env_var="REDIS_URL")
        can_connect_args_list = _monkeypatch_can_connect_to_socket_fails(monkeypatch)
        status = requirement.check_status(
            dict(REDIS_URL="redis://example.com:1234/"),
            local_state,
            'default',
            UserConfigOverrides())
        assert dict(host='example.com', port=1234, timeout_seconds=0.5) == can_connect_args_list[0]
        assert dict(host='localhost', port=6379, timeout_seconds=0.5) == can_connect_args_list[1]

        assert not status
        expected = "Cannot connect to Redis at redis://example.com:1234/."
        assert expected == status.status_description
Beispiel #18
0
    def __init__(self, directory_path, registry):
        self.directory_path = directory_path
        if registry is None:
            registry = PluginRegistry()
        self.registry = registry

        self.name = None
        self.description = ''
        self.icon = None
        self.commands = dict()
        self.default_command_name = None
        self.project_file_count = 0
        self.conda_meta_file_count = 0
        self.env_specs = dict()
        self.default_env_spec_name = None
Beispiel #19
0
    def check(dirname):
        _monkeypatch_pwd(monkeypatch, dirname)

        status = SimpleStatus(success=True, description='Service added.')
        status.requirement = RedisRequirement(PluginRegistry(),
                                              env_var='REDIS_URL',
                                              options=dict(type='redis'))

        _monkeypatch_add_service(monkeypatch, status)

        code = _parse_args_and_run_subcommand(
            ['conda-kapsel', 'add-service', 'redis'])
        assert code == 0

        out, err = capsys.readouterr()
        assert (
            'Service added.\n' +
            'Added service redis to the project file, its address will be in REDIS_URL.\n'
        ) == out
        assert '' == err
Beispiel #20
0
    def check_provide_contents(dirname):
        environ = dict()
        local_state_file = LocalStateFile.load_for_directory(dirname)
        local_state_file.set_service_run_state("myservice", dict(port=42))
        requirement = EnvVarRequirement(PluginRegistry(), env_var="FOO")
        status = requirement.check_status(environ, local_state_file, 'default', UserConfigOverrides())
        context = ProvideContext(environ=environ,
                                 local_state_file=local_state_file,
                                 default_env_spec_name='default',
                                 status=status,
                                 mode=PROVIDE_MODE_DEVELOPMENT)

        def transform_it(state):
            assert 42 == state['port']
            state['port'] = 43
            state['foo'] = 'bar'
            return 1234

        result = context.transform_service_run_state("myservice", transform_it)
        assert 1234 == result
        assert dict(port=43, foo='bar') == local_state_file.get_service_run_state("myservice")
Beispiel #21
0
    def check_provide_contents(dirname):
        environ = dict()
        local_state_file = LocalStateFile.load_for_directory(dirname)
        requirement = EnvVarRequirement(PluginRegistry(), env_var="FOO")
        status = requirement.check_status(environ, local_state_file, 'default', UserConfigOverrides())
        context = ProvideContext(environ=environ,
                                 local_state_file=local_state_file,
                                 default_env_spec_name='default',
                                 status=status,
                                 mode=PROVIDE_MODE_DEVELOPMENT)
        workpath = context.ensure_service_directory("foo")
        assert os.path.isdir(workpath)
        assert workpath.endswith("foo")
        parent = os.path.dirname(workpath)
        assert parent.endswith("services")
        parent = os.path.dirname(parent)
        assert parent == dirname

        # be sure we can create if it already exists
        workpath2 = context.ensure_service_directory("foo")
        assert os.path.isdir(workpath2)
        assert workpath == workpath2
Beispiel #22
0
    def check_fails_while_listing_installed(dirname):
        def sabotaged_installed_command(prefix):
            from conda_kapsel.internal import conda_api
            raise conda_api.CondaError("sabotage!")

        monkeypatch.setattr('conda_kapsel.internal.conda_api.installed',
                            sabotaged_installed_command)

        project_dir_disable_dedicated_env(dirname)
        local_state = LocalStateFile.load_for_directory(dirname)

        requirement = CondaEnvRequirement(
            registry=PluginRegistry(),
            env_specs=dict(
                default=EnvSpec('default', ['not_a_real_package'], [])))
        environ = minimal_environ(PROJECT_DIR=dirname)
        status = requirement.check_status(
            environ, local_state, 'default',
            UserConfigOverrides(inherited_env=environ.get(conda_env_var)))
        assert status.status_description.startswith(
            "Conda failed while listing installed packages in ")
        assert status.status_description.endswith(": sabotage!")
Beispiel #23
0
def test_find_by_service_type_unknown():
    registry = PluginRegistry()
    found = registry.find_requirement_by_service_type(service_type='blah', env_var='FOO', options=dict())
    assert found is None
Beispiel #24
0
def test_find_by_class_name_conda_env():
    registry = PluginRegistry()
    found = registry.find_provider_by_class_name(class_name="CondaEnvProvider")
    assert found is not None
    assert isinstance(found, CondaEnvProvider)
def test_download_item_is_none_not_a_string_or_dict():
    problems = []
    requirements = []
    DownloadRequirement._parse(PluginRegistry(), varname='FOO', item=None, problems=problems, requirements=requirements)
    assert ["Download name FOO should be followed by a URL string or a dictionary describing the download."] == problems
    assert len(requirements) == 0
Beispiel #26
0
def _parse_args_and_run_subcommand(argv):
    parser = ArgumentParser(
        prog="conda-kapsel",
        description="Actions on kapsels (runnable projects).")

    # future: make setup.py store our version in a version.py then use that here
    # parser.add_argument('-v', '--version', action='version', version='0.1')

    subparsers = parser.add_subparsers(help="Sub-commands")

    parser.add_argument('-v', '--version', action='version', version=version)

    def add_directory_arg(preset):
        preset.add_argument(
            '--directory',
            metavar='PROJECT_DIR',
            default='.',
            help=
            "Project directory containing kapsel.yml (defaults to current directory)"
        )

    def add_env_spec_arg(preset):
        preset.add_argument('--env-spec',
                            metavar='ENVIRONMENT_SPEC_NAME',
                            default=None,
                            action='store',
                            help="An environment spec name from kapsel.yml")

    def add_prepare_args(preset):
        add_directory_arg(preset)
        add_env_spec_arg(preset)
        all_supported_modes = list(_all_ui_modes)
        # we don't support "ask about every single thing" mode yet.
        all_supported_modes.remove(UI_MODE_TEXT_ASK_QUESTIONS)
        preset.add_argument('--mode',
                            metavar='MODE',
                            default=UI_MODE_TEXT_DEVELOPMENT_DEFAULTS_OR_ASK,
                            choices=_all_ui_modes,
                            action='store',
                            help="One of " + ", ".join(_all_ui_modes))

    def add_env_spec_name_arg(preset):
        preset.add_argument(
            '-n',
            '--name',
            metavar='ENVIRONMENT_SPEC_NAME',
            action='store',
            help="Name of the environment spec from kapsel.yml")

    preset = subparsers.add_parser(
        'init',
        help="Initialize a directory with default project configuration")
    add_directory_arg(preset)
    preset.set_defaults(main=init.main)

    preset = subparsers.add_parser(
        'run', help="Run the project, setting up requirements first")
    add_prepare_args(preset)
    preset.add_argument('command',
                        metavar='COMMAND_NAME',
                        default=None,
                        nargs='?',
                        help="A command name from kapsel.yml")
    preset.add_argument('extra_args_for_command',
                        metavar='EXTRA_ARGS_FOR_COMMAND',
                        default=None,
                        nargs=REMAINDER)
    preset.set_defaults(main=run.main)

    preset = subparsers.add_parser(
        'prepare',
        help="Set up the project requirements, but does not run the project")
    add_prepare_args(preset)
    preset.set_defaults(main=prepare.main)

    preset = subparsers.add_parser(
        'clean',
        help=
        "Removes generated state (stops services, deletes environment files, etc)"
    )
    add_directory_arg(preset)
    preset.set_defaults(main=clean.main)

    if not conda_kapsel._beta_test_mode:
        preset = subparsers.add_parser(
            'activate',
            help=
            "Set up the project and output shell export commands reflecting the setup"
        )
        add_prepare_args(preset)
        preset.set_defaults(main=activate.main)

    preset = subparsers.add_parser(
        'archive',
        help=
        "Create a .zip, .tar.gz, or .tar.bz2 archive with project files in it")
    add_directory_arg(preset)
    preset.add_argument('filename', metavar='ARCHIVE_FILENAME')
    preset.set_defaults(main=archive.main)

    preset = subparsers.add_parser('upload',
                                   help="Upload the project to Anaconda Cloud")
    add_directory_arg(preset)
    preset.add_argument('-s',
                        '--site',
                        metavar='SITE',
                        help='Select site to use')
    preset.add_argument(
        '-t',
        '--token',
        metavar='TOKEN',
        help='Auth token or a path to a file containing a token')
    preset.add_argument('-u',
                        '--user',
                        metavar='USERNAME',
                        help='User account, defaults to the current user')
    preset.set_defaults(main=upload.main)

    preset = subparsers.add_parser(
        'add-variable',
        help="Add a required environment variable to the project")
    preset.add_argument('vars_to_add',
                        metavar='VARS_TO_ADD',
                        default=None,
                        nargs=REMAINDER)
    preset.add_argument('--default',
                        metavar='DEFAULT_VALUE',
                        default=None,
                        help='Default value if environment variable is unset')
    add_directory_arg(preset)
    preset.set_defaults(main=variable_commands.main_add)

    preset = subparsers.add_parser(
        'remove-variable',
        help="Remove an environment variable from the project")
    add_directory_arg(preset)
    preset.add_argument('vars_to_remove',
                        metavar='VARS_TO_REMOVE',
                        default=None,
                        nargs=REMAINDER)
    preset.set_defaults(main=variable_commands.main_remove)

    preset = subparsers.add_parser('list-variables',
                                   help="List all variables on the project")
    add_directory_arg(preset)
    preset.set_defaults(main=variable_commands.main_list)

    preset = subparsers.add_parser(
        'set-variable',
        help="Set an environment variable value in kapsel-local.yml")
    preset.add_argument('vars_and_values',
                        metavar='VARS_AND_VALUES',
                        default=None,
                        nargs=REMAINDER)
    add_directory_arg(preset)
    preset.set_defaults(main=variable_commands.main_set)

    preset = subparsers.add_parser(
        'unset-variable',
        help="Unset an environment variable value from kapsel-local.yml")
    add_directory_arg(preset)
    preset.add_argument('vars_to_unset',
                        metavar='VARS_TO_UNSET',
                        default=None,
                        nargs=REMAINDER)
    preset.set_defaults(main=variable_commands.main_unset)

    preset = subparsers.add_parser(
        'add-download',
        help="Add a URL to be downloaded before running commands")
    add_directory_arg(preset)
    preset.add_argument('filename_variable',
                        metavar='ENV_VAR_FOR_FILENAME',
                        default=None)
    preset.add_argument('download_url', metavar='DOWNLOAD_URL', default=None)
    preset.add_argument(
        '--filename',
        help="The name to give the file/folder after downloading it",
        default=None)
    preset.add_argument('--hash-algorithm',
                        help="Defines which hash algorithm to use",
                        default=None,
                        choices=_hash_algorithms)
    preset.add_argument(
        '--hash-value',
        help="The expected checksum hash of the downloaded file",
        default=None)
    preset.set_defaults(main=download_commands.main_add)

    preset = subparsers.add_parser(
        'remove-download',
        help="Remove a download from the project and from the filesystem")
    add_directory_arg(preset)
    preset.add_argument('filename_variable',
                        metavar='ENV_VAR_FOR_FILENAME',
                        default=None)
    preset.set_defaults(main=download_commands.main_remove)

    preset = subparsers.add_parser('list-downloads',
                                   help="List all downloads on the project")
    add_directory_arg(preset)
    preset.set_defaults(main=download_commands.main_list)

    service_types = PluginRegistry().list_service_types()
    service_choices = list(map(lambda s: s.name, service_types))

    def add_service_variable_name(preset):
        preset.add_argument('--variable',
                            metavar='ENV_VAR_FOR_SERVICE_ADDRESS',
                            default=None)

    preset = subparsers.add_parser(
        'add-service',
        help="Add a service to be available before running commands")
    add_directory_arg(preset)
    add_service_variable_name(preset)
    preset.add_argument('service_type',
                        metavar='SERVICE_TYPE',
                        default=None,
                        choices=service_choices)
    preset.set_defaults(main=service_commands.main_add)

    preset = subparsers.add_parser('remove-service',
                                   help="Remove a service from the project")
    add_directory_arg(preset)
    preset.add_argument('variable', metavar='SERVICE_REFERENCE', default=None)
    preset.set_defaults(main=service_commands.main_remove)

    preset = subparsers.add_parser('list-services',
                                   help="List services present in the project")
    add_directory_arg(preset)
    preset.set_defaults(main=service_commands.main_list)

    def add_package_args(preset):
        preset.add_argument('-c',
                            '--channel',
                            metavar='CHANNEL',
                            action='append',
                            help='Channel to search for packages')
        preset.add_argument('packages',
                            metavar='PACKAGES',
                            default=None,
                            nargs=REMAINDER)

    preset = subparsers.add_parser(
        'add-env-spec', help="Add a new environment spec to the project")
    add_directory_arg(preset)
    add_package_args(preset)
    add_env_spec_name_arg(preset)
    preset.set_defaults(main=environment_commands.main_add)

    preset = subparsers.add_parser(
        'remove-env-spec', help="Remove an environment spec from the project")
    add_directory_arg(preset)
    add_env_spec_name_arg(preset)
    preset.set_defaults(main=environment_commands.main_remove)

    preset = subparsers.add_parser(
        'list-env-specs', help="List all environment specs for the project")
    add_directory_arg(preset)
    preset.set_defaults(main=environment_commands.main_list_env_specs)

    preset = subparsers.add_parser(
        'add-packages', help="Add packages to one or all project environments")
    add_directory_arg(preset)
    add_env_spec_arg(preset)
    add_package_args(preset)
    preset.set_defaults(main=environment_commands.main_add_packages)

    preset = subparsers.add_parser(
        'remove-packages',
        help="Remove packages from one or all project environments")
    add_directory_arg(preset)
    add_env_spec_arg(preset)
    preset.add_argument('packages',
                        metavar='PACKAGE_NAME',
                        default=None,
                        nargs='+')
    preset.set_defaults(main=environment_commands.main_remove_packages)

    preset = subparsers.add_parser(
        'list-packages',
        help="List packages for an environment on the project")
    add_directory_arg(preset)
    add_env_spec_arg(preset)
    preset.set_defaults(main=environment_commands.main_list_packages)

    def add_command_name_arg(preset):
        preset.add_argument('name',
                            metavar="NAME",
                            help="Command name used to invoke it")

    preset = subparsers.add_parser('add-command',
                                   help="Add a new command to the project")
    add_directory_arg(preset)
    command_choices = list(ALL_COMMAND_TYPES) + ['ask']
    command_choices.remove(
        "conda_app_entry")  # conda_app_entry is sort of silly and may go away
    preset.add_argument('--type',
                        action="store",
                        choices=command_choices,
                        help="Command type to add")
    add_command_name_arg(preset)
    add_env_spec_arg(preset)
    preset.add_argument('command',
                        metavar="COMMAND",
                        help="Command line or app filename to add")
    preset.set_defaults(main=command_commands.main)

    preset = subparsers.add_parser('remove-command',
                                   help="Remove a command from the project")
    add_directory_arg(preset)
    add_command_name_arg(preset)
    preset.set_defaults(main=command_commands.main_remove)

    preset = subparsers.add_parser('list-commands',
                                   help="List the commands on the project")
    add_directory_arg(preset)
    preset.set_defaults(main=command_commands.main_list)

    # argparse doesn't do this for us for whatever reason
    if len(argv) < 2:
        print("Must specify a subcommand.", file=sys.stderr)
        parser.print_usage(file=sys.stderr)
        return 2  # argparse exits with 2 on bad args, copy that

    try:
        args = parser.parse_args(argv[1:])
    except SystemExit as e:
        return e.code

    # '--directory' is used for all subcommands now, but may not be always
    if 'directory' in args:
        args.directory = os.path.abspath(args.directory)
    return args.main(args)
Beispiel #27
0
 def req(env_var, options=None):
     return EnvVarRequirement(registry=PluginRegistry(), env_var=env_var, options=options)
Beispiel #28
0
def test_requirement_repr():
    requirement = EnvVarRequirement(registry=PluginRegistry(), env_var='FOO')
    assert "EnvVarRequirement(env_var='FOO')" == repr(requirement)
Beispiel #29
0
def test_requirement_status_repr():
    requirement = EnvVarRequirement(registry=PluginRegistry(), env_var='FOO')
    status = requirement.check_status(dict(FOO=''), tmp_local_state_file(), 'default', UserConfigOverrides())
    assert "RequirementStatus(False,'Environment variable FOO is not set.',EnvVarRequirement(env_var='FOO'))" == repr(
        status)