spage

command module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 17, 2025 License: GPL-3.0 Imports: 3 Imported by: 0

README

Spage

This projects aims to function 'as' Ansible, but hugely more performant. By taking an Ansible playbook + inventory as input, it will generate a Go program that can be compiled for a specific host. The end result is a generated .go file that can be compiled and shipped to the target host.

To create such a program, this project ships the spage binary, with which you can target Ansible playbooks + inventories. Output looks like this:

$ spage generate -p playbook.yaml
Processing node pkg.TaskNode "ensure were in arch iso" "shell": &{Execute:lsblk -f | grep "/run/archiso/bootmnt" && exit 0 || exit 1 Revert: ModuleInput:<nil>}
Processing node pkg.TaskNode "create ssh dir" "shell": &{Execute:mkdir -p .ssh Revert: ModuleInput:<nil>}
Processing node pkg.TaskNode "copy ssh key" "shell": &{Execute:curl -sSL https://github.com/AlexanderGrooff.keys > .ssh/authorized_keys Revert: ModuleInput:<nil>}
Compiling graph to code:
- Step 0:
  - ensure were in arch iso
  - create ssh dir
- Step 1:
  - copy ssh key
Required inputs:
Processing node pkg.TaskNode "ensure were in arch iso" "shell": &{Execute:lsblk -f | grep "/run/archiso/bootmnt" && exit 0 || exit 1 Revert: ModuleInput:<nil>}
Processing node pkg.TaskNode "create ssh dir" "shell": &{Execute:mkdir -p .ssh Revert: ModuleInput:<nil>}
Processing node pkg.TaskNode "copy ssh key" "shell": &{Execute:curl -sSL https://github.com/AlexanderGrooff.keys > .ssh/authorized_keys Revert: ModuleInput:<nil>}
Compiling graph to code:
- Step 0:
  - ensure were in arch iso
  - create ssh dir
- Step 1:
  - copy ssh key
Required inputs:

This will generate a generated/tasks.go file, which can be compiled for a specific host. That file looks like this:

package generated

import (
    "github.com/AlexanderGrooff/spage/pkg"
    "github.com/AlexanderGrooff/spage/pkg/modules"
)

var GeneratedGraph = pkg.Graph{
  RequiredInputs: []string{
  },
  Tasks: [][]pkg.GraphNode{
      []pkg.GraphNode{
          pkg.Task{Name: "ensure were in arch iso", Module: "shell", Register: "", Params: modules.ShellInput{Execute: "lsblk -f | grep \"/run/archiso/bootmnt\" && exit 0 || exit 1", Revert: ""}, RunAs: "", When: ""},
          pkg.Task{Name: "create ssh dir", Module: "shell", Register: "", Params: modules.ShellInput{Execute: "mkdir -p .ssh", Revert: ""}, RunAs: "", When: ""},
      },
      []pkg.GraphNode{
          pkg.Task{Name: "copy ssh key", Module: "shell", Register: "", Params: modules.ShellInput{Execute: "curl -sSL https://github.com/AlexanderGrooff.keys > .ssh/authorized_keys", Revert: ""}, RunAs: "", When: ""},
      },
  },
}

Project structure

spage makes use of modules to execute tasks, just like Ansible. Modules are located in the pkg/modules directory. This includes modules such as shell, template, systemd, etc.

Ansible vs Spage

By default, Spage will generate a program that is functionally identical to Ansible. However, Spage also allows for more complex behavior, such as conditional tasks, multiple hosts, and more. Spage acts as a drop-in replacement for Ansible, so any playbook that can be run with Ansible can also be run with Spage. There are extra features that Spage offers:

  • Revert functionality: Spage will automatically revert any changes made by a task if the task fails. You can specify a revert task for each task in the playbook.
  • Parallel execution: Spage will automatically parallelize tasks across all hosts, and you can control the flow with before/after.
  • No Python dependency: Spage is a single binary that can be run on any system.

Usage

go generate
# OR
go run . generate -p playbook.yaml
# OR
go run generate_tasks.go -file playbook.yaml

# Run across an inventory
go run generated/tasks.go -i inventory.yaml
# Or compile for a specific host and run
go run generated/tasks.go -i inventory.yaml

TODO:

  • Add more modules
  • Add revert conditions revert_when
  • Make template variables case insensitive
  • Should we compile assets (templates, files) along with the code?
  • Hook up host facts like release, os, etc. This should happen dynamically and only fetch the required host facts.
  • Expression support:
    • "x is defined"
  • Read ansible.cfg variables such as [defaults] roles_path = roles/:shared_roles/ and [privilege_escalation] become_flags = -H -S
  • Add config option to prevent revert tasks
  • vars_prompt on play
  • gather_facts on play
  • vars on play
  • Don't allow interactive commands in temporal executor, or define an option that allows for signals/disallows interactivity.

Differences between Spage and Ansible

  • Playbooks are allowed to start without - tasks:. It assumes hosts: localhost and runs locally.
  • Parallel execution mode and reverts tasks by default.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
pkg

Jump to

Keyboard shortcuts

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