Skip to content

Commit

Permalink
simplify infos/status
Browse files Browse the repository at this point in the history
  • Loading branch information
Markus Raab authored and Janldeboer committed Jan 16, 2023
1 parent db109da commit 485ba17
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 93 deletions.
97 changes: 40 additions & 57 deletions doc/CONTRACT.ini
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ description = any non-empty string disables the stacking of plugins.
type = list <string>
status = implemented
usedby = plugin spec
example = binary code
example = binary
description = Lists the requirements of the plugin.
This can be a name of a plugin, but you should always prefer
the name of providers.
Expand All @@ -238,6 +238,9 @@ description = Lists the requirements of the plugin.
that such a provider must be present anywhere in the backend. The name
can also directly refer to another plugin’s name.

If your plugin does not has native support for serializing binary
data, make sure that `infos/needs` contains `binary`.

[infos/recommends]
type = string
status = implemented
Expand Down Expand Up @@ -281,39 +284,7 @@ description = Load plugins as given (with arguments as in "kdb mount").


[infos/status]
type = vector<long enum>
{"default", 64000}, ; will be added by the build system for KDB_DEFAULT_STORAGE and KDB_DEFAULT_RESOLVER
{"recommended", 32000}, ; in case of doubt, use this plugin
{"productive", 8000}, ; actively used in productive environments, not only by maintainer
{"maintained", 4000}, ; actively used and fixed by maintainer (infos/author)
{"reviewed", 4000}, ; actively reviewed on every change and not by maintainer
{"conformant", 2000}, ; to indicate that e.g. a storage plugin fulfils all requirements of a storage plugin
{"compatible", 2000}, ; to indicate it will be compatible with its later versions
{"coverage", 2000}, ; unittests have full code coverage
{"specific", 1000}, ; means that the plugin is non-portable in order to gain some specific advantages for the user
; (i.e. in a positive sense specific/non-portable)
{"unittest", 1000}, ; substantial plugin unittests (testmod)
{"shelltest", 1000}, ; substantial unittests with shell
{"tested", 500}, ; extensively manually tested on every change
{"nodep", 250}, ; no external library dependencies, except the languages core deps, e.g. libstdc++ and other plugins in `needs`
{"libc", 250}, ; uses libc only, no deps of other language’s run-times, e.g., libstdc++
{"configurable", 50}, ; options available to modify behavior
{"final", 50}, ; no further extensions, configure options or features are desirable
{"global", 1}, ; suitable as global plugin
{"readonly", 0}, ; can only read data from files (only kdbGet implemented)
{"writeonly", 0}, ; can only write data to files (only kdbSet implemented)
{"preview", -50}, ; plugin in technical preview state
{"memleak", -250}, ; memleak in plugin or one of the libraries the plugin uses
{"experimental", -500}, ; not much tested, plugin is in early stage, disabled in CMake by default
{"difficult", -500}, ; the plugin is (unnecessarily) difficult to use
{"limited", -750}, ; cannot represent arbitrary data (i.e. very specific format)
{"unfinished", -1000}, ; important functionality still missing
{"old", -1000}, ; code base is old and should be refactored/improved
{"nodoc", -1000}, ; documentation is minimal
{"concept", -2000}, ; the plugin only exists to demonstrate something
{"orphan", -4000}, ; author does not respond and also otherwise not much knowledge about plugin is present
{"obsolete", -4000}, ; another plugin fulfils a similar functionality in a better way
{"discouraged", -32000}, ; only use the plugin if you really know what you are doing
type = vector<int enum #include "src/libs/tools/include/plugincontract.h">
status = implemented
usedby = plugin spec binding
description = Tags about how well-established and well-working a plugin is.
Expand All @@ -323,9 +294,8 @@ description = Tags about how well-established and well-working a plugin is.
Numerical values are allowed, too. Please argue in the infos/description why
numerical values are used.

When changing some value in the type, you need to copy the information to
src/libs/tools/src/plugindatabase.cpp
src/plugins/template/README.md
For individual values see:
src/libs/tools/include/plugincontract.h


[infos/version]
Expand All @@ -339,42 +309,55 @@ description = Exports the plugin version this plugin was compiled

The version implies how the plugin interface must look like.

[config/needs]

[infos/features/storage]
type = vector<enum #include "src/libs/tools/include/pluginfeatures.h">
status = implemented
usedby = plugin spec
description = Exports a plugin configuration needed by another plugin. All keys
below `config/needs` will be propagated to the backend configuration.
Usually a provider in infos/needs then will use this configuration.
Alternatively, it can be provided if it avoids conflicts with some
other plugins.
usedby = plugin
description = Tags about how feature-full a storage plugin is.

It presents the plugin configuration needed so that
the plugin works properly. Typically the configuration is not for the
plugin itself, but for other needed plugins (in infos/needs).
Different features can be combined.

For individual features see:
src/libs/tools/include/pluginfeatures.h

[infos/environment]
type = string
status = PROPOSED
status = implemented
usedby = plugin kdb-plugin-info
example = HOME USER
description = List all environment variables the plugin
may access.
description = List all environment variables the plugin may access.

Note: Not listed environment variables do not mean that there
are none (the clause is only proposed, not yet implemented).
Grep for `getenv` to list all environment variables.
Space separated list of environment variables.

An empty list means that no environment variables influences
the behavior of the plugin.


[infos/dependencies/_]
type = string
status = PROPOSED
status = implemented
usedby = plugin kdb-plugin-info
example = libyajl-dev
description = The list of dependencies a plugin has for
a specific package management system (like deb, rpm,
arch, homebrew, ...).

Note: Not listed dependencies do not mean that there
are none (the clause is only proposed, not yet implemented).
See `infos/status` with `nodep` for up-to-date information.
Space separated list of dependencies.

An empty list means that only language core deps are used,
e.g. libc or libstdc++.


[config/needs]
status = implemented
usedby = plugin spec
description = Exports a plugin configuration needed by another plugin. All keys
below `config/needs` will be propagated to the backend configuration.
Usually a provider in infos/needs then will use this configuration.
Alternatively, it can be provided if it avoids conflicts with some
other plugins.

It presents the plugin configuration needed so that
the plugin works properly. Typically the configuration is not for the
plugin itself, but for other needed plugins (in infos/needs).
5 changes: 5 additions & 0 deletions doc/METADATA.ini
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ description="The spaces/tabs used between a comment and the beginning of the
An error needs to be emitted if non-ignored spaces are present."
example=

[indentation]
status=proposal
type= string
description= Preserves whitespace in front of the key used for indentation.


[internal/<plugin>/*]
status= implemented
Expand Down
19 changes: 19 additions & 0 deletions doc/news/_preparation_next_release.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,25 @@ The differences are 21 ms for the old implementation and 12 ms for the copy-on-w
## Plugins

The following text lists news about the [plugins](https://www.libelektra.org/plugins/readme) we updated in this release.
The following section lists news about the [plugins](https://www.libelektra.org/plugins/readme) we updated in this release.

### Contract

We simplified and extended the plugin's contract, mostly related to `infos/status`.
`infos/status` describes the development status of a plugin.
It is used for automatic selection of the best plugin during mounting.

- many redundant tags were removed
- tags that are actually features (like `readonly`) were moved to `infos/features/storage`
(currently not used by any tools but we intend to use this for the test framework and advanced mounting features)
- tag `nodep` replaced by `infos/dependencies/_`
- introduced `infos/environment` to indicate if environment variables can influence the plugin (or mountpoint)
- tag `nodoc` renamed to `documented`
- to avoid duplication, the tags are now described in header files:
- src/libs/tools/include/plugincontract.h
- src/libs/tools/include/pluginfeatures.h

Done in collaboration with _(Markus Raab, Klemens Böswirth, René Schwaiger, <add name>)_.

### yajl

Expand Down
8 changes: 8 additions & 0 deletions doc/tutorials/storage-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ sudo kdb umount user:/tests/storage

. For more information on why we allow “holes” in the hierarchy, please take a look [here](../decisions/5_implemented/holes.md).

Use the `directory/holes` tag in `infos/features/storage` to indicate that your storage plugin supports this feature.

[markdown shell recorder]: https://master.libelektra.org/tests/shell/shell_recorder/tutorial_wrapper

## Differentiate Between Empty Keys and Keys Containing an Empty String
Expand Down Expand Up @@ -100,6 +102,8 @@ kdb rm -r user:/tests/storage
sudo kdb umount user:/tests/storage
```

Use the `type` tag in `infos/features/storage` to indicate that your storage plugin supports this feature.

## Support Values Inside Non-Leaf Keys

Sometimes the most “natural” mapping of key-value pairs to a file format might cause a storage plugin to not be able to store values in so-called directory (non-leaf) keys.
Expand Down Expand Up @@ -158,6 +162,8 @@ sudo kdb umount user:/tests/storage

. To make sure that your storage plugin works correctly, please just replace `yamlcpp` with the name of your plugin and verify that the test above still works.

Use the `directory/value` tag in `infos/features/storage` to indicate that your storage plugin supports this feature.

## Support Array And Non-Array Data Properly

You already learned about the array syntax and the mandatory `array` metakey in the [array tutorial](arrays.md). Now it is time to check, if your storage plugin supports array and non-array keys properly. Let us look at a concrete example. We use a key set that contains the following keys as example:
Expand Down Expand Up @@ -303,6 +309,8 @@ sudo kdb umount user:/tests/hosts

As you can see by setting the order metakey in the respective KDB entries, we can manipulate the order in which entries get written to the hosts file. Also when importing from the initial hosts file, the plugin stores the correct order in the meta KeySet.

Use the `array` tag in `infos/features/storage` to indicate that your storage plugin supports this feature.

<!--
TODO: Add section about relative keys (See also: https://issues.libelektra.org/51)
-->
18 changes: 18 additions & 0 deletions src/libs/tools/include/plugincontract.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{"default", 64000}, //< to be used as default, will be added by the build system for KDB_DEFAULT_STORAGE and KDB_DEFAULT_RESOLVER
{"recommended", 32000}, //< in case of doubt, use this plugin
{"productive", 8000}, //< actively used in productive environments, not only by maintainer
{"maintained", 4000}, //< actively used and improved by maintainer (infos/author)
{"compatible", 2000}, //< will be compatible with its later versions
{"tested/unit", 1000}, //< substantial plugin unittests (testmod)
{"tested/shell", 1000}, //< substantial shell-recorder tests (README.md)
{"tested/fuzz", 1000}, //< tested using a fuzzer tool like AFL
{"documented", 1000}, //< all features are described in documentation (README.md)
{"configurable", 0}, //< plugin configuration available to modify behavior
{"global", 0}, //< suitable as global plugin
{"private", -250}, //< uses private header files from Elektra
{"memleak", -250}, //< memleak in plugin or one of the libraries the plugin uses
{"experimental", -4000}, //< plugin is in early stage, disabled in CMake by default
{"difficult", -8000}, //< the plugin is (unnecessarily) difficult to use
{"concept", -16000}, //< only a concept of how such a plugin could be done, needs proper rewrite
{"obsolete", -32000}, //< another plugin fulfils a similar functionality in a better way
{"discouraged", -64000}, //< only use the plugin if you really know what you are doing
19 changes: 19 additions & 0 deletions src/libs/tools/include/pluginfeatures.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"read", //< Can read from configuration files
"write", //< Can write to configuration files
"spec/*/*", //< Supports the standard spec for the format, e.g. spec/toml/v1.0.0-rc.3
"preserves/order", //< Preserves order of file structure (see order in doc/METADATA.ini)
"preserves/comment", //< Preserves comments (see comment/# in doc/METADATA.ini)
"preserves/comment/empty", //< Preserves empty lines in comments
"preserves/indentation", //< Preserves indentation around key and values (see indentation in doc/METADATA.ini)
"limited", //< Only specific structures of KeySets can be stored. This is for special purpose formats like hosts, fstab or passwd.
"arbitrary/keyset", //< Storage plugins should be able to read any (valid) config file and produce a KeySet. The few plugins marked with this tag, find also a config file for any KeySet.
"arbitrary/metadata", //< Also supports any other metadata (not listed in infos/metadata)
"directory/value", //< Supports non-leaf keys with value
"directory/holes", //< Support for holes within the hierarchy (not every directory needs to be present)
"type", //< Support for Elektra's types
"array", //< Support for arrays
"format/array", //< Has a specific serialization format for arrays (i.e. not #0=value)
"format/hierarchy", //< Has a specific serialization format for hierarchy (i.e. not dir/key=value)
"format/type", //< Has a specific serialization format for various types (i.e. not bool="0")
"format/human/read", //< The format is intended to be read by humans.
"format/human/write", //< The format is intended to be written by humans.
37 changes: 1 addition & 36 deletions src/libs/tools/src/plugindatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,43 +140,8 @@ bool hasProvides (PluginDatabase const & pd, std::string which)
} // namespace


// TODO: directly use data from CONTRACT.ini
const std::map<std::string, int> PluginDatabase::statusMap = {
// clang-format off
{"default", 64000},
{"recommended", 32000},
{"productive", 8000},
{"maintained", 4000},
{"reviewed", 4000},
{"conformant", 2000},
{"compatible", 2000},
{"coverage", 2000},
{"specific", 1000},

{"unittest", 1000},
{"shelltest", 1000},
{"tested", 500},
{"nodep", 250},
{"libc", 250},
{"configurable", 50},
{"final", 50},
{"global", 1},
{"readonly", 0},
{"writeonly", 0},
{"preview", -50},
{"memleak", -250},
{"experimental", -500},
{"difficult", -500},
{"limited", -750},
{"unfinished", -1000},
{"old", -1000},
{"nodoc", -1000},
{"concept", -2000},
{"orphan", -4000},
{"obsolete", -4000},
{"discouraged", -32000},

// clang-format on
#include <plugincontract.h>
};


Expand Down

0 comments on commit 485ba17

Please sign in to comment.