genesis

package module
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Mar 9, 2017 License: MIT Imports: 10 Imported by: 0

README

Genesis: A tool for building installers

Genesis is a Go package for building self-contained, self-extracting installers. It is intended as a configuration management utility for offline systems and devices, but it can be used for pretty much any system. Genesis can install, roll back, and report status. You can construct groups of tasks and define conditional dependencies.

Genesis is designed to configure a system from scratch. No initial setup is required. Go's ability to cross-compile static binaries makes it easy to generate installers for other platforms.

Motivation

Most configuration management systems (chef, ansible, etc.) don't work well for devices because they make some assumptions that don't hold for these systems. These assumptions are:

  1. disposability
  2. preconfiguration

These assumptions hold true for cloud servers and virtual machines, which is the typical target of configuration management. For hardware devices and similar, these assumptions often fail.

Design Goals

Genesis is built with a few key design goals in mind.

1. Minimize assumptions about the target system.

Genesis tries to make as few assumptions about the target system as we can. This allows it to target more systems. It also means less manual a priori setup. Here are some assumptions Genesis tries to avoid:

  • Network connectivity
  • Specific OS
  • Preinstalled software (python, ruby, bash, etc)
  • Availability of command line utilities (grep, awk, etc).
2. Provide status information.

A configuration management system should do more than configure a system. It should also describe the current status of the system and show how the system's current state differs from the desired state. This allows the user to make informed decisions about what to do next, or how to modify the installer.

3. Be able to roll back changes.

The Genesis software should be able to undo changes it makes to the system. Obviously there are limits to this, and Genesis will never be perfect at this. However, it should make reasonable attempts to restore the system to its previous state.

4. Able to be run by a non-expert.

Hardware systems are often delivered to a customer, and the customer gains complete control of the system. It is critical that non-expert users be able to update a system.

Usage

Gensis consists of two parts: a set of modules, and an installer package. Each module performs a specific configuration task, such as: creating a directory, inserting a line in a file, or creating a user. The official Genesis modules are contained in the modules directory. However, a module can live anywhere. To create a custom module, it must only satisfy the Module interface.

The second component is the installer. The installer handles all the complicated stuff of figuring out which tasks should run, and storing information about previous states.

Creating an Installer

Here is a very simple example showing how to build an installer.

package main

import (
    "github.com/wx13/genesis/installer"
    "github.com/wx13/genesis/modules"
)

func main() {

    inst := installer.New()
    defer inst.Done()

    inst.AddTask(modules.Mkdir{Path: "/tmp/genesis_example"})

    aptSection := installer.NewSection("Install some debian packages.")
    pkgs := []string{"git", "gitk", "tig", "screen"}
    for _, pkg := range pkgs {
        aptSection.AddTask(modules.Apt{Name: pkg})
    }
    inst.Add(aptSection)

}

which produces this:

genesis screenshot

See the example directory for more examples.

There are a few pieces here. First off, we import the installer package and the modules package, and create a new installer instance. Notice that we defer the inst.Done() command. Here's why: when we add tasks to the installer, those tasks don't get run right away. Which order they run in could depend on circumstances, so they get stored up by the installer. The inst.Done() command actually runs the installation.

To add a task, we can simply run AddTask with its argument being a module instance. As you can see above, we can also create named sections, and add tasks to those sections.

Building an Installer

There are two ways to build the installer: manually or with genesis's assistance. Both begin by building the exectable with:

go build [FILE]

or

GOOS=linux GOARCH=arm go build [FILE]

if you are cross-compiling.

Manual build

The installer extracts zip data from the end of itself. So you can create the full installer by appending the zip data.

zip -r files.zip files
cat files.zip >> installer
zip -A installer

The last command fixes the zip file indexing to account for the executable prepended to the zip data.

Automated build

There are a couple of issues with building manually. First off, you must make sure you zip up all the correct files with correct relative paths. If you have different versions of your installer (e.g. installer versus updater), you have to manually manage which files to zip for each. Finally, you have to remember to correct the zip file index or else your installer will fail.

Thankfully, genesis has a solution to this. To build the self-extracting installer from a binary, just run:

./installer build [list of dirs]

This will figure out which files are needed, look for them in the current directory, and create a self-contained installer at 'installer.x'. You can optionally specify a list of directories to look for files in (instead of the current directory).

This will fail for cross-compiled binaries, because you won't be able to execute the binary on the build system. Instead run:

go run installer.go -x installer build [list of dirs]

Running the installer

To run the installer, place it on the target system and execute it with one of the standard commands: "status", "install", or "remove". Use the "-h" flag to see the help screen. Each of the above commands has its own help screen as well.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Store *store.Store
View Source
var Tmpdir string

Functions

func DoerHash

func DoerHash(doer Doer) string

func ExpandHome

func ExpandHome(name string) string

ExpandHome expands a leading tilde to the user's home directory.

func FileExists

func FileExists(path string) bool

FileExists is a helper function to check if a file exists.

func IsRunning added in v0.2.0

func IsRunning(pattern string) (bool, error)

IsRunning checks to see if a process is running.

func StringHash

func StringHash(id string) string

Types

type Doer

type Doer interface {
	Do() (bool, error)
	Undo() (bool, error)
	Status() (Status, error)
	ID() string
	Files() []string
}

Doer can do and undo things.

type Facts

type Facts struct {
	Arch     string
	ArchType string
	OS       string
	Hostname string
	Username string
	Distro   string
}

Facts stores discovered information about the target system.

func GatherFacts added in v0.3.1

func GatherFacts() Facts

GatherFacts learns stuff about the target system.

type Module

type Module interface {
	Install() (string, error)
	Remove() (string, error)
	Status() (Status, string, error)
	ID() string      // Description of module action
	Files() []string // list of files needed by module
}

Module is an interface for all the modules.

type Status

type Status int

Status represents a Pass/Fail/Unknown.

const (
	StatusPass Status = iota
	StatusFail
	StatusUnknown
)

Directories

Path Synopsis
example
Package installer is the installer for the genesis package.
Package installer is the installer for the genesis package.
Package store provides support for keeping track of changes to files.
Package store provides support for keeping track of changes to files.

Jump to

Keyboard shortcuts

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