opsi-cli: Introduction to the new opsi command line interface
At the opsiconf opsiconf 2022, we announced a new command line tool to work with opsi environments. We also offered a quick preview of the new tool. opsi-cli
is now available as part of opsi-utils
>= 4.2.0.187 and as opsi package in our public repositories at download.uib.de. It can be used to access backend functions of an opsi config server via RPC and is highly customizable.
In this blog post, I shall give a short introduction to the new opsi-cli
. I will also write about the motivation, the design concept, and our implementation. At the end of the article, you can find installation instructions.
Motivation
Currently there are a plethora of command line tools to interact with opsi. The various components of opsi-utils
and opsi-python
scripts each have their own command line options, structure, output formats and design paradigms. opsi-python
scripts make use of python libraries installed in the underlying operating system and are therefore dependent on those. Some backend operations use the RPC interface, while others work around the opsiconfd to directly access the underlying data structures.
With all this in mind, the goal was to design a tool which gives access to the same functions (and more!) while also keeping a coherent and robust scheme. Also, backend functions should be more easily accessible while maintaining user-based access restrictions.
Design
We designed opsi-cli
to fulfill the following requirements
- Consistent form of options, parameters, inputs and outputs
- Compact binary executables for linux, macOS and Windows
- Dynamically extensible via custom python plugins
- Interaction with opsiconfd via RPC Interface only
- Proper distinguishing between payload (to stdout) and logging/errors/debugoutput (to stderr)
Step by step, we intend to implement parts of opsi-utils
(and more) as commands in opsi-cli
and keep the opsi-utils
commands as wrappers calling opsi-cli
behind the scenes, to maintain backwards compatibility.
opsi-cli
is structured to have multiple levels of commands and sub-commands, as inspired by the docker
command line interface for instance. The general endpoint opsi-cli
has multiple commands (or groups), each of which have sub-commands. The entry point as well as the commands and sub-commands can each have options affecting everything hierarchically below them. That means that an option set for a sub-command affects only the sub-command itself, while an option set for a command (group) affects all sub-commands of that command. Options set at entry point level affect all commands (e.g. --log-level
or --output-format
). The option --help
exists on every level and can be used to show details about the available options and/or sub-commands at that point. opsi-cli
is intended to fulfill one specific task and then exit with a meaningful exit code (not to be run as service).
Implementation
We decided to implement opsi-cli
in python, using the module click (or rich_click for beautiful colored outputs). The core of opsi-cli
is a binary that contains the basic commands config, self and plugin as well as some more specialized ones.
The configuration can hold access data for multiple opsi config servers (url, username and password) which are used to access backend methods. If no credentials are supplied, opsi-cli
tries to connect to https://localhost:4447 with credentials extracted from a local backend (which will only work if opsi-cli
is run directly on the config server).
There is a system- and a user-specific directory for plugins which are loaded dynamically at run-time. Those plugins can be imported, exported and exchanged between instances of opsi-cli. For zsh, bash and fish (and probably for powershell at some point in the future) there is an autocompletion feature (by pressing [Tab] / [Tab] [Tab]) which can be installed for more comfortable handling.
opsi-cli
can output data in different ways, depending on the entry point level option --output-format
. This way output can be optimized for human readability or efficiency in compression/transmission. Available formats are currently auto
, json
, pretty-json
, msgpack
, table
and csv
. As payload and logging are sent to different streams, multiple opsi-cli
calls can be chained (output to input) by using pipes.
How to get started
opsi-cli
is contained in opsi-utils
>= 4.2.0.187. That means once you upgrade opsi-utils
on your config server to any of these versions, opsi-cli
will already be available. As there is a local backend from which credentials can be extracted (provided the calling user has the required permissions), opsi-cli
can be used without supplying any additional service and user information.
To use opsi-cli on a different host (like a Windows machine), the easiest way to get it is to use the opsi package opsi-cli
from our public repositories at download.uib.de. For access to an opsi service, credentials must be supplied to opsi-cli either by entry point level options (--service
, --username
, --password
) or by storing the credentials on the client side (see opsi-cli config service add --help
).
Warning
Currently opsi-cli
is in a proposal state. At the moment we do not guarantee stability of the interface. It may very well be necessary for us to introduce breaking changes in the way opsi-cli
works. The plugin format and handling especially may be subject to change. Obviously we try to avoid breaking things, but sometimes it is better to correct design flaws early instead of carrying them through as legacy code.
Have fun playing around with opsi-cli, feel free to explore the new possibilities and please contact us if you have suggestions or feedback.