env: make spack config edit
and spack config get
environment-aware
- with no arguments, these commands will now edit or dump the environment's `spack.yaml` file. - users may not know where named environments live - this makes it convenient for users to get to the spack.yaml configuration file for their named environment.
This commit is contained in:
parent
25f8abb963
commit
8d92fd6640
@ -3,7 +3,13 @@
|
|||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
import os
|
||||||
|
|
||||||
|
import llnl.util.tty as tty
|
||||||
|
|
||||||
import spack.config
|
import spack.config
|
||||||
|
import spack.environment as ev
|
||||||
|
|
||||||
from spack.util.editor import editor
|
from spack.util.editor import editor
|
||||||
|
|
||||||
@ -27,6 +33,7 @@ def setup_parser(subparser):
|
|||||||
get_parser.add_argument('section',
|
get_parser.add_argument('section',
|
||||||
help="configuration section to print. "
|
help="configuration section to print. "
|
||||||
"options: %(choices)s",
|
"options: %(choices)s",
|
||||||
|
nargs='?',
|
||||||
metavar='SECTION',
|
metavar='SECTION',
|
||||||
choices=spack.config.section_schemas)
|
choices=spack.config.section_schemas)
|
||||||
|
|
||||||
@ -43,29 +50,81 @@ def setup_parser(subparser):
|
|||||||
help="configuration section to edit. "
|
help="configuration section to edit. "
|
||||||
"options: %(choices)s",
|
"options: %(choices)s",
|
||||||
metavar='SECTION',
|
metavar='SECTION',
|
||||||
|
nargs='?',
|
||||||
choices=spack.config.section_schemas)
|
choices=spack.config.section_schemas)
|
||||||
|
edit_parser.add_argument(
|
||||||
|
'--print-file', action='store_true',
|
||||||
|
help="print the file name that would be edited")
|
||||||
|
|
||||||
|
|
||||||
|
def _get_scope_and_section(args):
|
||||||
|
"""Extract config scope and section from arguments."""
|
||||||
|
scope = args.scope
|
||||||
|
section = args.section
|
||||||
|
|
||||||
|
# w/no args and an active environment, point to env manifest
|
||||||
|
if not args.section:
|
||||||
|
env = ev.get_env(args, 'config edit', required=False)
|
||||||
|
if env:
|
||||||
|
scope = env.env_file_config_scope_name()
|
||||||
|
|
||||||
|
# set scope defaults
|
||||||
|
elif not args.scope:
|
||||||
|
if section == 'compilers':
|
||||||
|
scope = spack.config.default_modify_scope()
|
||||||
|
else:
|
||||||
|
scope = 'user'
|
||||||
|
|
||||||
|
return scope, section
|
||||||
|
|
||||||
|
|
||||||
def config_get(args):
|
def config_get(args):
|
||||||
spack.config.config.print_section(args.section)
|
"""Dump merged YAML configuration for a specific section.
|
||||||
|
|
||||||
|
With no arguments and an active environment, print the contents of
|
||||||
|
the environment's manifest file (spack.yaml).
|
||||||
|
|
||||||
|
"""
|
||||||
|
scope, section = _get_scope_and_section(args)
|
||||||
|
|
||||||
|
if scope and scope.startswith('env:'):
|
||||||
|
config_file = spack.config.config.get_config_filename(scope, section)
|
||||||
|
if os.path.exists(config_file):
|
||||||
|
with open(config_file) as f:
|
||||||
|
print(f.read())
|
||||||
|
else:
|
||||||
|
tty.die('environment has no %s file' % ev.manifest_name)
|
||||||
|
|
||||||
|
elif section is not None:
|
||||||
|
spack.config.config.print_section(section)
|
||||||
|
|
||||||
|
else:
|
||||||
|
tty.die('`spack config get` requires a section argument '
|
||||||
|
'or an active environment.')
|
||||||
|
|
||||||
|
|
||||||
def config_blame(args):
|
def config_blame(args):
|
||||||
|
"""Print out line-by-line blame of merged YAML."""
|
||||||
spack.config.config.print_section(args.section, blame=True)
|
spack.config.config.print_section(args.section, blame=True)
|
||||||
|
|
||||||
|
|
||||||
def config_edit(args):
|
def config_edit(args):
|
||||||
if not args.scope:
|
"""Edit the configuration file for a specific scope and config section.
|
||||||
if args.section == 'compilers':
|
|
||||||
args.scope = spack.config.default_modify_scope()
|
|
||||||
else:
|
|
||||||
args.scope = 'user'
|
|
||||||
if not args.section:
|
|
||||||
args.section = None
|
|
||||||
|
|
||||||
config = spack.config.config
|
With no arguments and an active environment, edit the spack.yaml for
|
||||||
config_file = config.get_config_filename(args.scope, args.section)
|
the active environment.
|
||||||
editor(config_file)
|
|
||||||
|
"""
|
||||||
|
scope, section = _get_scope_and_section(args)
|
||||||
|
if not scope and not section:
|
||||||
|
tty.die('`spack config edit` requires a section argument '
|
||||||
|
'or an active environment.')
|
||||||
|
|
||||||
|
config_file = spack.config.config.get_config_filename(scope, section)
|
||||||
|
if args.print_file:
|
||||||
|
print(config_file)
|
||||||
|
else:
|
||||||
|
editor(config_file)
|
||||||
|
|
||||||
|
|
||||||
def config(parser, args):
|
def config(parser, args):
|
||||||
|
@ -483,9 +483,13 @@ def included_config_scopes(self):
|
|||||||
|
|
||||||
return scopes
|
return scopes
|
||||||
|
|
||||||
|
def env_file_config_scope_name(self):
|
||||||
|
"""Name of the config scope of this environment's manifest file."""
|
||||||
|
return 'env:%s' % self.name
|
||||||
|
|
||||||
def env_file_config_scope(self):
|
def env_file_config_scope(self):
|
||||||
"""Get the configuration scope for the environment's manifest file."""
|
"""Get the configuration scope for the environment's manifest file."""
|
||||||
config_name = 'env:%s' % self.name
|
config_name = self.env_file_config_scope_name()
|
||||||
return spack.config.SingleFileScope(config_name,
|
return spack.config.SingleFileScope(config_name,
|
||||||
self.manifest_path,
|
self.manifest_path,
|
||||||
spack.schema.env.schema,
|
spack.schema.env.schema,
|
||||||
|
93
lib/spack/spack/test/cmd/config.py
Normal file
93
lib/spack/spack/test/cmd/config.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# Copyright 2013-2018 Lawrence Livermore National Security, LLC and other
|
||||||
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from llnl.util.filesystem import mkdirp
|
||||||
|
|
||||||
|
import spack.config
|
||||||
|
import spack.environment as ev
|
||||||
|
from spack.main import SpackCommand
|
||||||
|
|
||||||
|
config = SpackCommand('config')
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_config_scope(mock_config):
|
||||||
|
assert config('get', 'compilers').strip() == 'compilers: {}'
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_config_scope_merged(mock_config):
|
||||||
|
low_path = mock_config.scopes['low'].path
|
||||||
|
high_path = mock_config.scopes['high'].path
|
||||||
|
|
||||||
|
mkdirp(low_path)
|
||||||
|
mkdirp(high_path)
|
||||||
|
|
||||||
|
with open(os.path.join(low_path, 'repos.yaml'), 'w') as f:
|
||||||
|
f.write('''\
|
||||||
|
repos:
|
||||||
|
- repo3
|
||||||
|
''')
|
||||||
|
|
||||||
|
with open(os.path.join(high_path, 'repos.yaml'), 'w') as f:
|
||||||
|
f.write('''\
|
||||||
|
repos:
|
||||||
|
- repo1
|
||||||
|
- repo2
|
||||||
|
''')
|
||||||
|
|
||||||
|
assert config('get', 'repos').strip() == '''repos:
|
||||||
|
- repo1
|
||||||
|
- repo2
|
||||||
|
- repo3'''
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_edit():
|
||||||
|
"""Ensure `spack config edit` edits the right paths."""
|
||||||
|
dms = spack.config.default_modify_scope()
|
||||||
|
dms_path = spack.config.config.scopes[dms].path
|
||||||
|
user_path = spack.config.config.scopes['user'].path
|
||||||
|
|
||||||
|
comp_path = os.path.join(dms_path, 'compilers.yaml')
|
||||||
|
repos_path = os.path.join(user_path, 'repos.yaml')
|
||||||
|
|
||||||
|
assert config('edit', '--print-file', 'compilers').strip() == comp_path
|
||||||
|
assert config('edit', '--print-file', 'repos').strip() == repos_path
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_get_gets_spack_yaml(mutable_mock_env_path):
|
||||||
|
env = ev.create('test')
|
||||||
|
|
||||||
|
config('get', fail_on_error=False)
|
||||||
|
assert config.returncode == 1
|
||||||
|
|
||||||
|
with env:
|
||||||
|
config('get', fail_on_error=False)
|
||||||
|
assert config.returncode == 1
|
||||||
|
|
||||||
|
env.write()
|
||||||
|
|
||||||
|
assert 'mpileaks' not in config('get')
|
||||||
|
|
||||||
|
env.add('mpileaks')
|
||||||
|
env.write()
|
||||||
|
|
||||||
|
assert 'mpileaks' in config('get')
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_edit_edits_spack_yaml(mutable_mock_env_path):
|
||||||
|
env = ev.create('test')
|
||||||
|
with env:
|
||||||
|
assert config('edit', '--print-file').strip() == env.manifest_path
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_edit_fails_correctly_with_no_env(mutable_mock_env_path):
|
||||||
|
output = config('edit', '--print-file', fail_on_error=False)
|
||||||
|
assert "requires a section argument or an active environment" in output
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_get_fails_correctly_with_no_env(mutable_mock_env_path):
|
||||||
|
output = config('get', fail_on_error=False)
|
||||||
|
assert "requires a section argument or an active environment" in output
|
@ -49,20 +49,6 @@
|
|||||||
'build_stage:': ['patha', 'pathb']}}
|
'build_stage:': ['patha', 'pathb']}}
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
|
||||||
def mock_config(tmpdir):
|
|
||||||
"""Mocks the configuration scope."""
|
|
||||||
real_configuration = spack.config.config
|
|
||||||
|
|
||||||
spack.config.config = spack.config.Configuration(
|
|
||||||
*[spack.config.ConfigScope(name, str(tmpdir.join(name)))
|
|
||||||
for name in ['low', 'high']])
|
|
||||||
|
|
||||||
yield spack.config.config
|
|
||||||
|
|
||||||
spack.config.config = real_configuration
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def write_config_file(tmpdir):
|
def write_config_file(tmpdir):
|
||||||
"""Returns a function that writes a config file."""
|
"""Returns a function that writes a config file."""
|
||||||
|
@ -309,6 +309,20 @@ def mutable_config(tmpdir_factory, configuration_dir, config):
|
|||||||
spack.package_prefs.PackagePrefs.clear_caches()
|
spack.package_prefs.PackagePrefs.clear_caches()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def mock_config(tmpdir):
|
||||||
|
"""Mocks two configuration scopes: 'low' and 'high'."""
|
||||||
|
real_configuration = spack.config.config
|
||||||
|
|
||||||
|
spack.config.config = spack.config.Configuration(
|
||||||
|
*[spack.config.ConfigScope(name, str(tmpdir.join(name)))
|
||||||
|
for name in ['low', 'high']])
|
||||||
|
|
||||||
|
yield spack.config.config
|
||||||
|
|
||||||
|
spack.config.config = real_configuration
|
||||||
|
|
||||||
|
|
||||||
def _populate(mock_db):
|
def _populate(mock_db):
|
||||||
r"""Populate a mock database with packages.
|
r"""Populate a mock database with packages.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user