package module
Version: v1.3.0 Latest Latest

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

Go to latest
Published: Aug 27, 2019 License: BSD-3-Clause Imports: 14 Imported by: 0


= opsi

Create an OPSI package (opsi.org) without any kind of OPSI infrastructure itself.
Useful for pipelines such as Travis, GitLab CI/CD when using the suggested OPSI
VMware image is cumbersome.

An alternative to the default opsi-makepackage command, just without any
dependencies whatsoever. No VMWare image, no Python 2/3, no cpio, no tar, no

Windows? Check

Raspberry? Check

Mac? Check.

= Why would you want to do this?

You can always use the OPSI provided `opsi-makepackage` command, previously
known as `opsi-makeproductfile`.  This requires a complete OPSI setup though.
The suggested way is to use the provided https://opsi.org/try-opsi/[virtual
image] which makes VMWare part of the game.  As of OPSI 4.1, the commandline
tools are written in Python, which would make a standalone non-VMWare build
pipeline cumbersome to set up.
So if your packaging is separated from your depot servers, this standalone tool
might come in handy.  One single executable, no dependencies.

= Installation

== Prerequisites

=== Build

- Go (golang.org)

=== Runtime

- Windows, Linux, Mac, or any other platform that Go supports

No OPSI and no local tools required. 

=== Build from source

$ go get gitlab.com/jhinrichsen/opsi

=== Download executable release

For precompiled binaries, use gitlab's 'Download Artifacts'.

= Run

== Help
$ opsi -h <1>
Usage: opsi [key1=value1]*
  -control string
        OPSI control file (default "./OPSI/control")
  -datadir string
        data directory used as input (default "./CLIENT_DATA")
  -into string
        OPSI package destination directory (default ".")
        keep OPSI interim workbench for debugging purposes
  -opsidir string
        OPSI directory used as input (default "./OPSI")
<1> Display help

== Sample package from `testdata` directory

$ opsi --control testdata/simple/OPSI/control --datadir=testdata/simple/CLIENT_DATA --opsidir=testdata/simple/OPSI <1>
<1> Create `simple_1.2.3-4.opsi` package in local (`.`) directory

== Controlfile templates

Control files may contain placeholder that are replaced with current values when
creating the package.  Given the following controlfile template snippet:
version: {{.package_version}} <1>

type: localboot
id: template
name: Template
description: Template based control file
version: {{.product_version}} <2>
<1>, <2> template values

Template values are written in default Go template syntax using mustache-like
double curly braces and a leading dot `.`.  Actual values can be passed via the

$ opsi package_version=4 product_version=1.2.3 <1>
$ opsi package_version=${BUILDNO} product_version=${VERSION} <2>
<1> hardcoded values
<2> Using the Jenkins build number for package version and a VERSION environment

Note that there is no OPSI related naming convention for naming template values,
use whatever you like.

= Drawbacks

The original OPSI packaging command has validity checks when creating a control
file, or a package.  E.g. `opsi-makepackage` will check the version number and
bail out if it does not fit an internal scheme.
`opsi` will allow you to create packages containing an illegal version number,
e.g. `3_1_2`.




View Source
const (
	// KEY_ID is OPSI's product_id
	KEY_ID = "product_id"

	// KEY_VERSION is OPSI's product_version
	KEY_VERSION = "product_version"

	// KEY_PACKAGE_VERSION is OPSI's package_version
	KEY_PACKAGE_VERSION = "package_version"
View Source
const (
	Controlfilename = "control"


This section is empty.


func Exists added in v1.0.0

func Exists(path string) (bool, error)

Exists returns whether the given file or directory exists or not

func GzipFile

func GzipFile(fromFilename string, intoFilename string) (os.FileInfo, error)

GzipFile creates a gzip container

func IsTar

func IsTar(filename string) bool

IsTar determines if a filename ends in .tar (or .TAR, or any combination)

func IsTarGz

func IsTarGz(filename string) bool

IsTarGz determines if a filename ends in .tar.gz (or .TAR.GZ, or any combination)

func ListContent

func ListContent(filename string) (treeprint.Tree, error)

ListContent returns filenames included in an .opsi archive. Supports .tar for now. TODO add cpio support

func ListControlfile added in v1.0.0

func ListControlfile(tr *tar.Reader, w io.Writer) error

Writes control file to writer

func Package

func Package(p PackageParameter) error

Package creates an OPSI package. no care has been taken to minimize interim file creation. TODO research io.Pipe() approach The OPSI control file is treated special, in that it is a required parameter, can optionally contain dynamic metadata (version, BUILD_ID, ...). Its resolved values can be used in other supporting files in the OPSI directory.

func ReaderFor

func ReaderFor(filename string, tr *tar.Reader) (*tar.Reader, error)

ReaderFor returns an appropriate reader for either .tar or .tar.gz files

func Resolve

func Resolve(content string, m Metadata) (bytes.Buffer, error)

Resolve replaces placeholder with actual metadata

func TmpDir added in v1.0.0

func TmpDir() (string, error)

TmpDir returns an OPSI related temporary directory. Caller is responsible for removing/ housekeeping


type DirMapper added in v1.3.0

type DirMapper struct {
	Basedir string

func NewDirMapper added in v1.3.0

func NewDirMapper(basedir string) DirMapper

func (*DirMapper) Left added in v1.3.0

func (a *DirMapper) Left(dir string) string

left = original, prepend base directory

func (*DirMapper) Right added in v1.3.0

func (a *DirMapper) Right(dir string) string

right = translated, remove base directory https://github.com/golang/go/issues/18358

type Metadata

type Metadata struct {
	Entries map[string]string

Metadata carries key value mappings for OPSI

func NewMetadata

func NewMetadata(entries []string, separator string) (*Metadata, error)

NewMetadata will initialize from a list of key value pairs. Existing entries remain unchanged if any entry cannot be parsed.

func Parse

func Parse(control io.Reader) (Metadata, error)

Parse reads metadata from control files. All sections and all keys are lowercase

func (*Metadata) DottedVersion

func (a *Metadata) DottedVersion() string

DottedVersion returns the version in dotted format, e.g. 3.1.2

func (*Metadata) Filename

func (a *Metadata) Filename() string

Filename derives final OPSI package name from metadata. <product_id>_<product_version>-<package_version>.opsi missing metadata will result in defaults: product_id: "undefined" product_version: 0.0.0 package_version: 0

func (*Metadata) ID

func (a *Metadata) ID() string

ID is a shortcut for key product_id

func (*Metadata) Merge added in v1.0.0

func (a *Metadata) Merge(m Metadata)

Merge will merge non-existent key-value pairs from m to a existing keys will NOT be overwritten

func (*Metadata) PackageVersion added in v1.0.0

func (a *Metadata) PackageVersion() string

PackageVersion returns the package version

func (*Metadata) SetID added in v1.0.0

func (a *Metadata) SetID(s string)

ID is a shortcut for key product_id

func (*Metadata) SetPackageVersion added in v1.0.0

func (a *Metadata) SetPackageVersion(s string)

func (*Metadata) SetVersion added in v1.0.0

func (a *Metadata) SetVersion(s string)

func (*Metadata) UnderscoredVersion

func (a *Metadata) UnderscoredVersion() string

UnderscoredVersion returns the version in dotted format, e.g. 3_1_2

func (*Metadata) Version added in v1.0.0

func (a *Metadata) Version() string

Version returns the version in dotted format, e.g. 3.1.2

type PackageParameter

type PackageParameter struct {
	Basedir         string   // base directory for OPSI packaging
	Into            string   // Target directory for .opsi package, default "."
	Opsidir         string   // OPSI metadata directory, default "OPSI"
	Controlfilename string   // relative path into Opsidir, default "control"
	Payload         string   // OPSI payload directory, default "CLIENT_DATA"
	Workbench       string   // Temporary directory, default ""
	Metadata        Metadata // Dynamic variables, default empty/ none
	Keep            bool     // Keep interim artifacts

PackageParameter holds configuration for package creation

func NewPackageParameter added in v1.0.0

func NewPackageParameter() PackageParameter

NewPackageParameter returns default parameters for packaging. The only required parameter is the control file Defaults:

Into: '.'
Opsidir: './OPSI'
ControlFilename: 'control'
Payload: './CLIENT_DATA'
Workbench: "" which will use an internal temporary directory
Metadata: empty/ none


Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
t or T : Toggle theme light dark auto
y or Y : Canonical URL