\subsection*{Introduction}

Configuration in F\+L\+O\+S\+S unfortunately is often stored completely without validation. Notable exceptions are sudo ({\ttfamily sudoedit}), or user accounts ({\ttfamily adduser}) but in most cases you only get feedback of non-\/validating configuration when the application fails to start.

Elektra provides a generic way to validate any configuration file before it is written to disc.

\subsection*{User Interfaces}

Any of Elektra's user interfaces will work with the technique described in this tutorial, e.\+g.\+:

1.) {\ttfamily kdb qt-\/gui}\+: graphical user interface

2.) {\ttfamily kdb editor}\+: starts up your favourite text editor and allows you to edit configuration in any syntax. (generalization of {\ttfamily sudoedit})

3.) {\ttfamily kdb set}\+: manipulate or add individual configuration entries. (generalization of {\ttfamily adduser})

4.) Any other tool using Elektra to store configuration (e.\+g. if the application itself has capabilities to modify its configuration)

\subsection*{Metadata together with keys}

The most direct way to validate keys is

``` \begin{quote}
kdb mount validation.\+dump user/tutorial/together dump validation kdb vset user/tutorial/together/test 123 \char`\"{}\mbox{[}1-\/9\mbox{]}\mbox{[}0-\/9\mbox{]}$\ast$\char`\"{} \char`\"{}\+Not a number\char`\"{} kdb set user/tutorial/together/test abc \end{quote}
Error (\#42) occurred! Description\+: Key Value failed to validate Reason\+: Not a number ```

For all other plugins (except {\ttfamily validation}) the convenience tool {\ttfamily kdb vset} is missing. Let us see what {\ttfamily kdb vset} actually did\+:

``` \begin{quote}
kdb lsmeta user/tutorial/together/test \end{quote}
check/validation check/validation/match check/validation/message ```

So it only appended some metadata (data describing the data) next to the key, which we also could do by\+:

``` \section*{Following lines are (except for error conditions) identical to}

\section*{$>$ kdb vset user/tutorial/together/test 123 \char`\"{}\mbox{[}1-\/9\mbox{]}\mbox{[}0-\/9\mbox{]}$\ast$\char`\"{} \char`\"{}\+Not a number\char`\"{}}

\begin{quote}
kdb setmeta user/tutorial/together/test check/validation \char`\"{}\mbox{[}1-\/9\mbox{]}\mbox{[}0-\/9\mbox{]}$\ast$\char`\"{} kdb setmeta user/tutorial/together/test check/validation/match L\+I\+N\+E kdb setmeta user/tutorial/together/test check/validation/message \char`\"{}\+Not a number\char`\"{} kdb set user/tutorial/together/test 123 \end{quote}
```

The approach is not limited to validation via regular expressions, but any values-\/validation plugin can be used, e.\+g. \hyperlink{md_src_plugins_enum_README_src_plugins_enum_README_md}{enum}. For a full list refer to the section \char`\"{}\+Value Validation\char`\"{} in the \hyperlink{md_src_plugins_README_src_plugins_README_md}{list of all plugins}.

Note that it also easy \hyperlink{doc_tutorials_plugins_md}{to write your own (value validation) plugin}.

The drawbacks of this approach are\+:


\begin{DoxyItemize}
\item The administrator needs to take care that the validation plugins are available where needed.
\item Some metadata (in this case {\ttfamily check/validation}) needs to be stored next to the key which won't work with most configuration files. This is the reason why we explicitly used {\ttfamily dump} as storage in {\ttfamily kdb mount}.
\item After the key is removed, the validation information is gone, too.
\item It only works for the \hyperlink{doc_tutorials_namespaces_md}{namespace} where {\ttfamily vset} was used. In the example above we could override the cascading key {\ttfamily /tutorial/together/test} with the unvalidated key {\ttfamily dir/tutorial/together/test}.
\item You cannot validate structure of which keys must be present or absent.
\end{DoxyItemize}

\subsection*{Get started with spec}

These issues are resolved straightforward by separation of schemata (describing the configuration) and the configuration itself. The purpose of the \hyperlink{doc_tutorials_namespaces_md}{spec namespace} is to hold the schemata, the description of how to validate the keys of all other namespaces.

To make this work, we need a plugin that applies all metadata found in the {\ttfamily spec}-\/namespace to all other namespaces. This plugin is called {\ttfamily spec} and needs to be mounted globally (will be added by default with {\ttfamily kdb global-\/mount})\+:

``` \begin{quote}
kdb global-\/mount \end{quote}
```

Then we can write metadata to {\ttfamily spec} and see it for every cascading key\+:

``` \begin{quote}
kdb setmeta spec/tutorial/spec/test hello world kdb set user/tutorial/spec/test value kdb lsmeta /tutorial/spec/test \end{quote}
hello ```

But it also supports globbing ({\ttfamily \+\_\+} for any key, {\ttfamily ?} for any char, {\ttfamily \mbox{[}\mbox{]}} for character classes)\+:

``` \begin{quote}
kdb setmeta \char`\"{}spec/tutorial/spec/\+\_\+\char`\"{} new meta kdb lsmeta /tutorial/spec/test \end{quote}
hello new ```

So let us combine this functionality with validation plugins. So we would specify\+:

``` \begin{quote}
kdb setmeta spec/tutorial/spec/test check/validation \char`\"{}\mbox{[}1-\/9\mbox{]}\mbox{[}0-\/9\mbox{]}$\ast$\char`\"{} kdb setmeta spec/tutorial/spec/test check/validation/match L\+I\+N\+E kdb setmeta spec/tutorial/spec/test check/validation/message \char`\"{}\+Not a number\char`\"{} \end{quote}
```

Alternatively, we could mount a plugin that supports metadata, e.\+g. the {\ttfamily ni} plugin, and specify the configuration using a text editor (or {\ttfamily cat})\+:

``` \begin{quote}
kdb mount spec.\+ini spec/tutorial/spec ni cat $<$$<$ H\+E\+R\+E $>$ {\ttfamily kdb file spec/tutorial/spec} \end{quote}
\mbox{[}test\mbox{]} check/validation = \mbox{[}1-\/9\mbox{]}\mbox{[}0-\/9\mbox{]}$\ast$ check/validation/match = L\+I\+N\+E check/validation/message = Not a number H\+E\+R\+E \begin{quote}
kdb lsmeta /tutorial/spec/test \end{quote}
check/validation check/validation/match check/validation/message ```

As next step we need to correctly mount all validation plugins to {\ttfamily /tutorial/spec}. Because we have an extra specification of the validation, we can use this specification to assemble the plugins. We only have to specify where the mountpoint is (and which file name should be used), then we can mount the file according the specification and have validation for all namespaces\+:

``` \begin{quote}
kdb setmeta spec/tutorial/spec mountpoint spec-\/tutorial.\+dump kdb spec-\/mount /tutorial/spec kdb set /tutorial/spec/test wrong \end{quote}
Using name user/tutorial/spec/test Error (\#42) occurred! Description\+: Key Value failed to validate Reason\+: Not a number ```

\subsection*{Rejecting Configuration Keys}

Up to now we only discussed how to reject keys that have unwanted values. Sometimes, however, applications require the presence or absence of keys. There are many ways to do so directly supported by \hyperlink{md_src_plugins_spec_README_src_plugins_spec_README_md}{the spec plugin}. Another way is to trigger errors with the \hyperlink{md_src_plugins_error_README_src_plugins_error_README_md}{error plugin}\+:

``` \begin{quote}
kdb setmeta /tutorial/spec/should\+\_\+not\+\_\+be\+\_\+here trigger/error 10 kdb spec-\/mount /tutorial/spec kdb set /tutorial/spec/should\+\_\+not\+\_\+be\+\_\+here abc \end{quote}
Error (\#10) occurred! \begin{quote}
kdb get /tutorial/spec/should\+\_\+not\+\_\+be\+\_\+here \end{quote}
Did not find key ```

If we want to reject every optional key (and only want to allow required keys) we can use the plugin {\ttfamily required} as further discussed below.

\subsection*{Customized schemas}

Sometimes we already have configuration specifications given in some other format which is more compact and more directed to the needs of an individual application. We can write a plugin that parses that format and transform the content to key/value {\itshape and} metadata (describing how to validate).

For example, let us assume we have enum validations in the file {\ttfamily schema.\+txt}\+:

``` cat $>$ \$\+P\+W\+D/schema.txt $<$$<$ H\+E\+R\+E \%\+: notation T\+B\+D ? graph text semi \%\+: tool-\/support$\ast$ T\+B\+D ? none compiler ide \%\+: applied-\/to T\+B\+D ? none small real-\/world mountpoint file.\+txt plugins required H\+E\+R\+E ```

And by convention for keys ending with {\ttfamily $\ast$}, multiple values are allowed. So we want to transform above syntax to\+: \%\+:notation T\+B\+D ? graph text semi \%\+:tool-\/support$\ast$ T\+B\+D ? none compiler ide \%\+:applied-\/to T\+B\+D ? none small real-\/world

Lucky, we already have a plugin which allows us to so\+:

``` kdb mount \$\+P\+W\+D/schema.txt spec/tutorial/schema simplespeclang keyword/enum=\%\+:,keyword/assign=T\+B\+D kdb spec-\/mount /tutorial/schema ```

We configure the plugin {\ttfamily simplespeclang} so that it conforms to our \char`\"{}weird\char`\"{} syntax. Because in {\ttfamily schema.\+txt} we have the line {\ttfamily mountpoint file.\+txt} we can also mount the schema using {\ttfamily spec-\/mount}.

Now we have enforced that the 3 configuration options {\ttfamily notation tool-\/support$\ast$ applied-\/to} need to be present (and no other). For example we can import\+:

``` kdb import -\/s validate -\/c \char`\"{}format=\% \+: \%\char`\"{} /tutorial/schema simpleini $<$$<$ H\+E\+R\+E notation \+: graph tool-\/support \+: ? none applied-\/to \+: small H\+E\+R\+E ```

Or (afterwards) setting individual values\+:

``` kdb set /tutorial/schema/applied-\/to smal \# fails, not a valid enum ```

Or (in {\ttfamily sudoedit} fashion)\+:

``` kdb editor -\/s validate /tutorial/schema simpleini ``` 