llconf

command module
v0.0.0-...-1501d32 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 14, 2014 License: GPL-3.0 Imports: 12 Imported by: 0

README

LLConf (zined: "had to fork this, for the lulz!!")

Build Status

LLConf - Lisp Like configuration management

LLConf is a configuration management system. It is, just like Ruby and Cheff inspired by CFEngine. It has three main goals:

  • Make it feel natural to describe a machine state instead of a setup process
  • Be extendible
  • Keep it simple

Config Files

LLConf concatenates all files in the input folder recursively. You therefore are free to spilt your configuration up in as may files as your want.

Promises

LLConf evolved arround the concept of promises that are to be kept by a machine. Those familiar with CFEngine heard of the concept but the way its done in LLConf is quite different. In LLConf, everything done is a promise. There are no classes to select the promises you want to be met. Also, the amount of special promise types is kept to minimum. Instead what LLconf does is to help you building your own special promises by the use of named promises.

Named Promises

(name ( other promise ))

Named promises serve the purpose of naming a promise. This way, you can reuse the promise and improve the readablilty of your setup. There use is mandatory. Every other buildin promise has to be evaluated by testing a named promise.

Boolean

(and (promisses...)) (or (promisses ...))

The promises "(and)" and "(or)" are essential to combine promises and by that, create a tree of promises that have to be fullfilled. Both promises take a list of other promises. These are evaluated in order. The (and) promise stops evaluating and fails as soon as one promise in the list fails. The or promise stops evaluating and returns sucess as soon as one promise is successful.

Execution

At the and of the day, running llconf boils down to executing shell commands and interpreting there outputs. Since a promise can only be met or not, the evaluation of a execution is a simple check if the programm execution succeded or not. To ease reporting there are two ways to execute programms. They only differ by their name and the bucket their outcomes are storend into for later monitoring.

Tests

(test "command" "argument 1" "argument 2" ... "argument n")

Oftentimes you just want to check stuff and execute something else depending on the outcome. For example if you want to check if a process is running you don't want a report on how often the check that the process is running succeded. Ideally this should be always.

Changes

(change "command" "argument 1" "argument 2" ... "argument n")

When the process isn't isn't running and you have to change that, you surly want that be reported so if that change has to be done regualry, something ought to be wrong with either your machine or the setup you are tring to implement.

Pipes

(pipe (test) (test) (change) ... )

The standart unix toolbox is one of the most flexible tools for system adimistration out there. This all comes down to the simple concept of pipes. LLConf also supports pipes using the pipe promise. The standart output of every command is passed down as the standart input of the next one in the list. For obvious reasons you can only use (change) and (test) promises inside a (pipe) promise.

Changing directories

(indir ( change / test ))

To execute a program inside a specific directory, for example running a "git checkout" you can use the indir promise.

Getters

Two types of "Getters" in LLConf. Both allow you to retrieve a string and use it whereever you would use a string. The first one is the simple argument getter.

Arguments

You can pass arguments whenever you test a named promise.

For example

(hello world "foo" "bar")

will invoke the named promise "hello world" with the arguments "foo" and "bar". You can use these arguments using the argument getter [arg:n]. In this example [arg:0] will return "foo" and [arg:1] will return "bar"

Variables

Another type of getters allow you to use named variables. First, the scope of variables is similar to the scope of arguments, so basically variables are "named promise scoped". This means that every named promise creates a new dictionary by copying the dictionary of the surrounding promise. This way you can overwrite variables locally without affecting evaluations globally.

To get the contents of a variable you simply write

[var:name] (eg. [var:favorite_colour])

Variables can be set by using on of the following special promises:

(setvar "name" "value")

This promise stores the value "value" under the name "name"

(readvar "name (cmd))

This promise stores the standart output of the invoked command under the name "name". The command can be a (test) a (change) or a (pipe) promise.

Join

Sometimes you have to combine the contents of multible variables to one string. This is done by the "join" "getter" which simply joins the value of every getter following the join, eg:

(hello world
    (test "echo" [join [arg:0] " " [arg:1]]))

which will, when invoked like in the sample above, run the command "echo" with the argument "hello world".

Template Editing

LLConf leverages go's template engine. It expects json as the input to the template engine.

(template "{json}" "template-file" "output-file")

Since the template engine can handle arrays and objects you can easily can adapt the template to your needs. LLConf is not able to edit files. It is in my oppinion very dangerous to edit a file based on regular expressions, since you cant be really sure that the config file you are editing is

Updateing Config Files

LLConf keeps the parsed promise-tree in memory and only updates it if there is new and valid input. This way you can easily change the input files, using git or other means, and don't have to worry about backing up the last working state.

Samples

Keep mysql running
(mysql running
    (or (process match "mysqld")
        (change "/etc/init.d/mysql" "start")))

(process match
    (test "ps" "-C" [arg:0]))

It simply checks there is a mysqld process running and, if not, fires up the init script

Get THE source and keep it up to date
(keep the source "git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git" "/usr/src/linux")

(keep the source
    (or (and (git repo present [arg:1]) (git repo uptodate [arg:1]))
        (change "git" "clone" [arg:0])))

(git repo present
    (test "test" "-d" [join [arg:0] "/.git"]))

(git repo uptodate
  (and (indir [arg:0] (test "git" "fetch" "--all")
    (or (indir [arg:0] (test "git" "diff" "--quiet" "HEAD@{upstream}"))
        (indir [arg:0] (change "git" "reset" "--hard" "HEAD@{upstream}")))))

this example is a little more complicated. The promise named "keep the source" checks if there is a git clone present at the location specified as the second argument and if this repo is uptodate. If it isn't, it clones the repository specified as the first argument.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL