//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

=== Configuration

==== Files

Apache Karaf stores and loads all configuration in files located in the `etc` folder.

By default, the `etc` folder is located relatively to the `KARAF_BASE` folder. You can define another location
using the `KARAF_ETC` variable.

Each configuration is identified by a ID (the ConfigAdmin PID). The configuration files name follows the `pid.cfg`
name convention.

For instance, `etc/org.apache.karaf.shell.cfg` means that this file is the file used by the configuration with
`org.apache.karaf.shell` as PID.

A configuration file is a properties file containing key/value pairs:

----
property=value
----

In Apache Karaf, a configuration is PID with a set of properties attached.

Apache Karaf automatically loads all `*.cfg` files from the `etc` folder.

You can configure the behaviour of the configuration files using some dedicated properties in the
`etc/config.properties` configuration file:

----
...
#
# Configuration FileMonitor properties
#
felix.fileinstall.enableConfigSave = true
felix.fileinstall.dir    = ${karaf.etc}
felix.fileinstall.filter = .*\\.cfg
felix.fileinstall.poll   = 1000
felix.fileinstall.noInitialDelay = true
felix.fileinstall.log.level = 3
felix.fileinstall.log.default = jul
...
----

* `felix.fileinstall.enableConfigSave` flush back in the configuration file the changes performed directly on the
configuration service (ConfigAdmin). If `true`, any change (using `config:*` commands, MBeans, OSGi service) is
persisted back in the configuration false. Default is `true`.
* `felix.fileinstall.dir` is the directory where Apache Karaf is looking for configuration files. Default is `${karaf.etc`}
meaning the value of the `KARAF_ETC` variable.
* `felix.fileinstall.filter` is the file name pattern used to load only some configuration files. Only files matching
the pattern will be loaded. Default value is `.*\\.cfg` meaning *.cfg files.
* `felix.fileinstall.poll` is the polling interval (in milliseconds). Default value is `1000` meaning that Apache
Karaf "re-loads" the configuration files every second.
* `felix.fileinstall.noInitialDelay` is a flag indicating if the configuration file polling starts as soon as Apache
Karaf starts or wait for a certain time. If `true`, Apache Karaf polls the configuration files as soon as the configuration
service starts.
* `felix.fileinstall.log.level` is the log message verbosity level of the configuration polling service. More
this value is high, more verbose the configuration service is.
* `felix.fileinstall.log.default` is the logging framework to use, `jul` meaning Java Util Logging.

You can change the configuration at runtime by directly editiing the configuration file.

You can also do the same using the `config:*` commands or the ConfigMBean.

==== `config:*` commands

Apache Karaf provides a set of commands to manage the configuration.

===== `config:list`

`config:list` displays the list of all configurations available, or the properties in a given configuration (PID).

Without the `query` argument, the `config:list` command display all configurations, with PID, attached bundle and
properties defined in the configuration:

----
karaf@root()> config:list
----------------------------------------------------------------
Pid:            org.apache.karaf.service.acl.command.system.start-level
BundleLocation: mvn:org.apache.karaf.shell/org.apache.karaf.shell.console/4.0.0
Properties:
   service.guard = (&(osgi.command.scope=system)(osgi.command.function=start-level))
   * = *
   start-level = admin                           # admin can set any start level, including < 100
   start-level[/[^0-9]*/] = viewer               # viewer can obtain the current start level
   execute[/.*/,/[^0-9]*/] = viewer               # viewer can obtain the current start level
   execute = admin                           # admin can set any start level, including < 100
   service.pid = org.apache.karaf.service.acl.command.system.start-level
   start-level[/.*[0-9][0-9][0-9]+.*/] = manager # manager can set startlevels above 100
   execute[/.*/,/.*[0-9][0-9][0-9]+.*/] = manager # manager can set startlevels above 100
----------------------------------------------------------------
Pid:            org.apache.karaf.log
BundleLocation: mvn:org.apache.karaf.log/org.apache.karaf.log.core/4.0.0
Properties:
   service.pid = org.apache.karaf.log
   size = 500
   pattern = %d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
   felix.fileinstall.filename = file:/opt/apache-karaf-4.0.0/etc/org.apache.karaf.log.cfg
...
----

The `query` argument accepts a query using a LDAP syntax.

For instance, you can display details on one specific configuration using the following filter:

----
karaf@root()> config:list "(service.pid=org.apache.karaf.log)"
----------------------------------------------------------------
Pid:            org.apache.karaf.log
BundleLocation: mvn:org.apache.karaf.log/org.apache.karaf.log.core/4.0.0
Properties:
   felix.fileinstall.filename = file:/opt/apache-karaf-4.0.0/etc/org.apache.karaf.log.cfg
   pattern = %d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
   service.pid = org.apache.karaf.log
   size = 500
----

===== `config:edit`

`config:edit` is the first command to do when you want to change a configuration. `config:edit` command put you
in edition mode for a given configuration.

For instance, you can edit the `org.apache.karaf.log` configuration:

----
karaf@root()> config:edit org.apache.karaf.log
----

The `config:edit` command doesn't display anything, it just puts you in configuration edit mode. You are now ready
to use other config commands (like `config:property-append`, `config:property-delete`, `config:property-set`, ...).

If you provide a configuration PID that doesn't exist yet, Apache Karaf will create a new configuration (and so a new
configuration file) automatically.

All changes that you do in configuration edit mode are store in your console session: the changes are not directly
applied in the configuration. It allows you to "commit" the changes (see `config:update` command) or "rollback" and
cancel your changes (see `config:cancel` command).

===== `config:property-list`

The `config:property-list` lists the properties for the currently edited configuration.

Assuming that you edited the `org.apache.karaf.log` configuration, you can do:

----
karaf@root()> config:property-list
   felix.fileinstall.filename = file:/opt/apache-karaf-4.0.0/etc/org.apache.karaf.log.cfg
   pattern = %d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
   service.pid = org.apache.karaf.log
   size = 500
----

===== `config:property-set`

The `config:property-set` command update the value of a given property in the currently edited configuration.

For instance, to change the value of the `size` property of previously edited `org.apache.karaf.log` configuration,
you can do:

----
karaf@root()> config:property-set size 1000
karaf@root()> config:property-list
   felix.fileinstall.filename = file:/opt/apache-karaf-4.0.0/etc/org.apache.karaf.log.cfg
   pattern = %d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
   service.pid = org.apache.karaf.log
   size = 1000
----

If the property doesn't exist, the `config:property-set` command creates the property.

You can use `config:property-set` command outside the configuration edit mode, by specifying the `-p` (for configuration pid) option:

----
karaf@root()> config:property-set -p org.apache.karaf.log size 1000
karaf@root()> config:list "(service.pid=org.apache.karaf.log)"
----------------------------------------------------------------
Pid:            org.apache.karaf.log
BundleLocation: mvn:org.apache.karaf.log/org.apache.karaf.log.core/4.0.0
Properties:
   service.pid = org.apache.karaf.log
   size = 1000
   pattern = %d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
   felix.fileinstall.filename = file:/opt/apache-karaf-4.0.0/etc/org.apache.karaf.log.cfg
----

[NOTE]
====
Using the `pid` option, you bypass the configuration commit and rollback mechanism.
====

===== `config:property-append`

The `config:property-append` is similar to `config:property-set` command, but instead of completely replacing the
property value, it appends a string at the end of the property value.

For instance, to add 1 at the end of the value of the `size` property in `org.apache.karaf.log` configuration
(and so have 5001 for the value instead of 500), you can do:

----
karaf@root()> config:property-append size 1
karaf@root()> config:property-list
   service.pid = org.apache.karaf.log
   size = 5001
   pattern = %d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
   felix.fileinstall.filename = file:/opt/apache-karaf-4.0.0/etc/org.apache.karaf.log.cfg
----

Like the `config:property-set` command, if the property doesn't exist, the `config:property-set` command creates
the property.

You can use the `config:property-append` command outside the configuration edit mode, by specifying the `-p` (for configuration pid) option:

----
karaf@root()> config:property-append -p org.apache.karaf.log size 1
karaf@root()> config:list "(service.pid=org.apache.karaf.log)"
----------------------------------------------------------------
Pid:            org.apache.karaf.log
BundleLocation: mvn:org.apache.karaf.log/org.apache.karaf.log.core/4.0.0
Properties:
   service.pid = org.apache.karaf.log
   size = 5001
   pattern = %d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
   felix.fileinstall.filename = file:/opt/apache-karaf-4.0.0/etc/org.apache.karaf.log.cfg
----

[NOTE]
====
Using the `pid` option, you bypass the configuration commit and rollback mechanism.
====

===== `config:property-delete`

The `config:property-delete` command delete a property in the currently edited configuration.

For instance, you previously added a `test` property in `org.apache.karaf.log` configuration. To delete this `test`
property, you do:

----
karaf@root()> config:property-set test test
karaf@root()> config:property-list
   service.pid = org.apache.karaf.log
   size = 500
   pattern = %d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
   felix.fileinstall.filename = file:/opt/apache-karaf-4.0.0/etc/org.apache.karaf.log.cfg
   test = test
karaf@root()> config:property-delete test
karaf@root()> config:property-list
   service.pid = org.apache.karaf.log
   size = 500
   pattern = %d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
   felix.fileinstall.filename = file:/opt/apache-karaf-4.0.0/etc/org.apache.karaf.log.cfg
----

You can use the `config:property-delete` command outside the configuration edit mode, by specifying the `-p` (for configuration pid) option:

----
karaf@root()> config:property-delete -p org.apache.karaf.log test
----

===== `config:update` and `config:cancel`

When you are in the configuration edit mode, all changes that you do using `config:property*` commands are stored in "memory"
(actually in the console session).

Thanks to that, you can "commit" your changes using the `config:update` command. The `config:update` command will
commit your changes, update the configuration, and (if possible) update the configuration files.

For instance, after changing `org.apache.karaf.log` configuration with some `config:property*` commands, you have
to commit your change like this:

----
karaf@root()> config:edit org.apache.karaf.log
karaf@root()> config:property-set test test
karaf@root()> config:update
karaf@root()> config:list "(service.pid=org.apache.karaf.log)"
----------------------------------------------------------------
Pid:            org.apache.karaf.log
BundleLocation: mvn:org.apache.karaf.log/org.apache.karaf.log.core/4.0.0
Properties:
   service.pid = org.apache.karaf.log
   size = 500
   pattern = %d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
   felix.fileinstall.filename = file:/opt/apache-karaf-4.0.0/etc/org.apache.karaf.log.cfg
   test = test
----

On the other hand, if you want to "rollback" your changes, you can use the `config:cancel` command. It will cancel all
changes that you did, and return of the configuration state just before the `config:edit` command. The `config:cancel`
exits from the edit mode.

For instance, you added the test property in the `org.apache.karaf.log` configuration, but it was a mistake:

----
karaf@root()> config:edit org.apache.karaf.log
karaf@root()> config:property-set test test
karaf@root()> config:cancel
karaf@root()> config:list "(service.pid=org.apache.karaf.log)"
----------------------------------------------------------------
Pid:            org.apache.karaf.log
BundleLocation: mvn:org.apache.karaf.log/org.apache.karaf.log.core/4.0.0
Properties:
   service.pid = org.apache.karaf.log
   size = 500
   pattern = %d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
   felix.fileinstall.filename = file:/opt/apache-karaf-4.0.0/etc/org.apache.karaf.log.cfg
----

===== `config:delete`

The `config:delete` command completely delete an existing configuration. You don't have to be in edit mode to delete
a configuration.

For instance, you added `my.config` configuration:

----
karaf@root()> config:edit my.config
karaf@root()> config:property-set test test
karaf@root()> config:update
karaf@root()> config:list "(service.pid=my.config)"
----------------------------------------------------------------
Pid:            my.config
BundleLocation: null
Properties:
   service.pid = my.config
   test = test
----

You can delete the `my.config` configuration (including all properties in the configuration) using the `config:delete`
command:

----
karaf@root()> config:delete my.config
karaf@root()> config:list "(service.pid=my.config)"
karaf@root()>
----

===== `config:meta`

The `config:meta` command lists the meta type information related to a given configuration.

It allows you to get details about the configuration properties: key, name, type, default value, and description:

----
karaf@root()> config:meta -p org.apache.karaf.log
Meta type informations for pid: org.apache.karaf.log
key     | name    | type   | default                                                              | description
---------------------------------------------------------------------------------------------------------------------------------------
size    | Size    | int    | 500                                                                  | size of the log to keep in memory
pattern | Pattern | String | %d{ABSOLUTE} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n | Pattern used to display log entries
---- 

==== JMX ConfigMBean

On the JMX layer, you have a MBean dedicated to the management of the configurations: the ConfigMBean.

The ConfigMBean object name is: `org.apache.karaf:type=config,name=*`.

===== Attributes

The `Configs` attribute is a list of all configuration PIDs.

===== Operations

* `listProperties(pid)` returns the list of properties (property=value formatted) for the configuration `pid`.
* `deleteProperty(pid, property)` deletes the `property` from the configuration `pid`.
* `appendProperty(pid, property, value)` appends `value` at the end of the value of the `property` of the configuration `pid`.
* `setProperty(pid, property, value)` sets `value` for the value of the `property` of the configuration `pid`.
* `delete(pid)` deletes the configuration identified by the `pid`.
* `create(pid)` creates an empty (without any property) configuration with `pid`.
* `update(pid, properties)` updates a configuration identified with `pid` with the provided `properties` map.

