r2d4 / virgo

Graph-based Declarative Configuration Language
MIT License
134 stars 7 forks source link
configuration devops graph

Virgo Configuration Language

Most configuration problems reduce to graphs, e.g. Dockerfiles and Makefiles

But there are no graph-based configuration languages. So virgo is an attempt to make a programming language that optimizes for natural graph readability, editability, and representation.

Imagine dot language, but focused on config instead of presentation.

Virgo Logo

Virgo is a graph-based configuration language. It has two main features: edge definitions and vertex definitions. The Virgo configuration file then parses into an adjacency list. You can clearly achieve similar results from adding additional conventions and restrictions on YAML or JSON. Much like YAML optimized for human readability, Virgo optimizes for natural graph readability, editability, and representation.

Go

This repository contains a reference implementation written in Go, with yacc and lex definitions.

Python

There is a python implementation maintained at jwg4/pyvirgo which can also be found on PyPi.

// config.vgo

a -> b, c, d -> e <- f, g

Virgo Example

Example

// config.vgo

clean -> parser, lexer -> "src files" -> test

parser = `goyacc parser.y`
lexer  = `golex lex.l`
clean  = `rm lex.yy.go parser.go || true`
"test"   = `go test-v`
"src files"  = `go build ./...`

How to parse and topologically sort the graph with the Go library.

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "strings"

    "github.com/pkg/errors"
    "matt-rickard.com/virgo/pkg/virgo"
)

func main() {
    if err := run("config.go"); err != nil {
        log.Fatal(err)
        os.Exit(1)
    }
}

func run(fname string) error {
    f, err := ioutil.ReadFile(fname)
    if err != nil {
        return errors.Wrap(err, "reading file")
    }
    g, err := virgo.Parse(f)
    if err != nil {
        return errors.Wrap(err, "parsing virgo file")
    }

    nodes, err := virgo.TopSort(g)
    if err != nil {
        return errors.Wrap(err, "topological sort")
    }

    out := []string{}
    for _, n := range nodes {
        out = append(out, g.Vertices[n]...)
    }
    fmt.Println(strings.Join(out, "\n"))
    return nil
}

How to parse and topologically sort the graph with the Virgo CLI tool

$ virgo run build.vgo

Or topologically sort from a specific vertex

$ virgo run build.vgo:lexer

Virgo is Open for Proposals

I use virgo in a variety of ways for my own projects. That being said, I'm open to significant language change and feature proposals. Please open up a detailed issue and I'll do my best to respond. I'm also open to taking on more full time maintainers.

Language Reference

Edge Statement


a -> b, c -> d, e <- f <- g
a -> h
b -> h, i

Vertex Statement

vertex_definition_1 = `
    anything
    can
    go
    ${here}
`