User Guide ¶
Compspec provides a plugin-based strategy to extract metadata about some application or environment. This can include compatibility metadata about an application, or a graph of subsystem metadata about a resource like software, network, or similar. We currently support the following extractor plugins:
compspec-ior : for I/O metadata
compspec-spack : for a spack software subsystem graph
compspec-flux : for Flux resource graphs
If you haven’t read Installation you should do that first. We will give an example in the context of using IOR.
Example with IOR ¶
After installing both:
$ pip install compspec
$ pip install compspec-ior
You likely want to do an extractor. The general command looks like this:
$ compspec extract <name> <options>
For example, with IOR (using defaults):
$ compspec extract ior
And you can add additional arguments for IOR at the end of the line instead of using the defaults. An extractor can also have custom arguments. If you want to load from file, for example.
$ compspec extract ior --ior-load ior-data.json
Or if you want to save the compatibility json to file:
$ compspec extract --outfile test.json ior
We will have more documentation as the library is developed. For example, we will eventually be able to package and push to registries with ORAS.
Writing a Plugin ¶
Naming ¶
Here are some early tips to writing plugins.
Your plugin name should be
compspec-<name>
(for the repository / pypi package) and the module namecompspec_<name>
If you’d like to be under the compspec org please open an issue on any repository, we’d love to have you!
Organization ¶
A plugin typically has the following structure:
├── CHANGELOG.md
├── compspec_ior
│ ├── defaults.py
│ ├── __init__.py
│ ├── plugin.py
│ ├── schema.json
│ └── version.py
├── LICENSE
├── MANIFEST.in
├── pyproject.toml
├── pytest.ini
├── README.md
├── setup.cfg
└── setup.py
Of course the testing setup is up to you, but we recommend pytest and linting, etc.
Your Module ¶
-
In the
__init__.py
you are required to have aPlugin
that can be imported, which should be your subclass ofPluginBase
(described below) -
In the “defaults.py” you must define: - a namespace for your plugin (e.g., io.compspec.ior, it is typically like a URL but backwards) - a version for your schema - a schema_url (raw GitHub URL) where you can programmatically access the schema
All of the above, and your plugin structure, are validated.
Plugin Design ¶
The plugin should use the
compspec.plugins.PluginBase
class. It should define the following class attributes:
class Plugin(PluginBase):
"""
The IOR extractor plugin
"""
# These metadata fields are required (and checked for)
description = "IOR parallel I/O benchmarks"
namespace = defaults.namespace
version = defaults.spec_version
schema = defaults.schema_url
Those are all validated when your plugin is loaded into the registry, and it will fail with an error if you forget one. You should next provide a custom parser that has any special arguments / options you want to appear on the compspec command line. Make sure to namespace them according to your plugin. That might look like this (note it accepts the subparser as an argument):
def add_arguments(self, subparser):
"""
Add arguments for the plugin to show up in argparse
"""
ior = subparser.add_parser(
self.name,
formatter_class=argparse.RawTextHelpFormatter,
description=self.description,
)
# Ensure these are namespaced to your plugin
ior.add_argument(
"ior_args",
help="Arguments for IOR (defaults to reasonable set if not defined)",
nargs="*",
)
ior.add_argument(
"--ior-load",
dest="ior_load",
help="Load metadata from this file instead of extraction from system directly.",
)
You don’t need to return anything - by adding to the subparser, it will stick. You should also provide an “extract” function that takes “args” and “extra” expected from compspec. Your arguments will be available too.
This function should return key/value pairs of your metadata.
You do not need to namespace them, that will be done for you.
def extract(self, args, extra):
"""
Run IOR and map metadata into compspec schema.
"""
meta = {"field.a": "a", "field.b": "b"}
return meta
It’s entirely up to you how you want to implement this! For IOR, by default we assume running IOR (with user specific command line options).
But we also provide an
--ior-load
parameter that the user can specify to just load pre-generated data from file. As a design strategy, we
expose the function to parse this metadata into a flat list of attributes as a courtesy function, in case it is useful outside of using compspec.
Finally, you might want to provide an “in Python” example for using your plugin.
Testing ¶
We provide GitHub actions that you can use to validate your plugin schema. For example:
on:
pull_request: []
jobs:
validate-schema:
name: Validate schema
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Validate Schema
uses: compspec/actions/validate-schema@main
with:
schema: ./compspec_myname/schema.json
You should also provide tests that validate installing and using your plugin with compspec. As an example, this installs both, runs compspec with a few different configurations, and then runs an “in Python” example that doesn’t rely on the compspec command line utility:
jobs:
test:
name: Test IOR
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Install compspec
run: pip install compspec
- name: Install compspec-ior
run: pip install .
- name: Test with loading data
run: compspec extract ior --ior-load ./examples/test/ior-data.json
- name: Test Python
run: python ./examples/singleton-run.py
For all of the above, you can see compspec-ior as an example.