florist

package
v0.3.6 Latest Latest
Warning

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

Go to latest
Published: Mar 11, 2025 License: MIT Imports: 29 Imported by: 0

Documentation

Overview

Package florist helps to create non-idempotent, one-file-contains-everything installers/provisioners.

Index

Constants

View Source
const (
	DefOsPkgCacheValidity = 1 * time.Hour
)
View Source
const (
	WorkDir = "/tmp/florist.work"
)

Variables

This section is empty.

Functions

func CacheValidity

func CacheValidity() time.Duration

func Chgrp added in v0.3.6

func Chgrp(fpath string, groupname string) error

Chgrp sets the group of 'fpath' to the group ID of 'groupname'. See also Chown.

func Chown

func Chown(fpath string, username string) error

Chown sets the owner of 'fpath' to the user ID and primary group ID of 'username'. See also Chgrp.

func CmdRun

func CmdRun(log *slog.Logger, cmd *exec.Cmd) error

CmdRun runs 'cmd', redirecting its stdout and stderr to 'log.Debug'. CmdRun blocks until 'cmd' terminates.

func CopyFile

func CopyFile(
	srcPath string, dstPath string,
	mode os.FileMode, owner string,
) error

CopyFile copies file srcPath to dstPath, with mode and owner. The source and destination files reside in the "real" filesystem. Notes: - If dstPath exists, it will be overwritten. - Setting an owner different that the current user requires elevated privileges.

func CopyFileFs

func CopyFileFs(
	srcFs fs.FS, srcPath string, dstPath string,
	mode os.FileMode, owner string,
) error

CopyFileFs copies file srcPath to dstPath, with mode and owner. The source file resides in the srcFs filesystem (for example, via go:embed), while the destination file resides in the "real" filesystem. Notes: - If dstPath exists, it will be overwritten. - Setting an owner different that the current user requires elevated privileges.

func FileExists added in v0.3.3

func FileExists(fpath string) (bool, error)

Return true if file 'fpath' exists. WARNING Checking for file existence is racy and in certain cases can lead to security vulnerabilities. Think twice before using this. In the majority of cases, you can simply skip the existence check, since the next operation will fail in any case if the file doesn't exist.

Explanation of the TOCTOU vulnerability: https://wiki.sei.cmu.edu/confluence/display/c/FIO45-C.+Avoid+TOCTOU+race+conditions+while+accessing+files

func GroupSystemAdd

func GroupSystemAdd(groupname string) error

GroupSystemAdd adds group 'groupname'. It is not an error if 'groupname' already exists.

func JoinErrors

func JoinErrors(errs ...error) error

JoinErrors returns an error containing the joined error messages of 'errs'. If all elements of 'errs' are nil, JoinErrors returns nil. Does not preserve the error types nor provides Unwrap.

func ListFs

func ListFs(fsys fs.FS) []string

ListFs returns a list of the files (not directories) in fsys. In case of error, it encodes the error in a file name in the list.

func ListeningSockets

func ListeningSockets() (*sets.Set[string], error)

func Log

func Log() *slog.Logger

func LowLevelInit

func LowLevelInit(logOutput io.Writer, logLevel string, cacheValidity time.Duration) error

LowLevelInit should be called only by low-level test code. Absolutely do not call in non-test code! Call florist.MainInt instead!

func MainErr

func MainErr[T *struct{}](opts *Options) error

MainErr is a ready-made function for the main() of your installer. See also MainInt.

func MainInt

func MainInt(opts *Options) int

MainInt is a ready-made function for the main() of your installer.

Usage:

func main() {
	os.Exit(florist.MainInt(&florist.Options{
		SetupFn:     setup,
		ConfigureFn: configure,
	}))
}

func NetFetch

func NetFetch(client *http.Client, url string, hashType Hash, hash string, dstDir string) (string, error)

NetFetch uses client to download url to dstDir, returning the path of the downloaded file. Directory dstDir must exist. If after the download the hash doesn't match, it will return an error. If the file in dstDir exists and the hash matches, it will not be redownloaded.

func PrivateIPs

func PrivateIPs() ([]string, error)

func PublicIPs

func PublicIPs() ([]string, error)

func SkipIfNotDisposableHost

func SkipIfNotDisposableHost(t *testing.T)

SkipIfNotDisposableHost skips the test if it is running on a precious host.

func SupplementaryGroups

func SupplementaryGroups(username string, groups ...string) error

SupplementaryGroups adds 'username' to the supplementary groups 'groups'. It is an error if any of 'groups' does not exist (create them beforehand with GroupSystemAdd).

func TemplateFromFs

func TemplateFromFs(srcFs fs.FS, srcPath string, tmplData any) (string, error)

TemplateFromFs reads file srcPath in filesystem srcFs and renders its contents // as a template with data tmplData.

func TemplateFromFsWithDelims

func TemplateFromFsWithDelims(srcFs fs.FS, srcPath string, tmplData any) (string, error)

TemplateFromFsWithDelims reads file srcPath in filesystem srcFs and renders its contents as a template with data tmplData, with "<<", ">>" as template delimiters. This is useful to escape the default delimiters "{{", "}}" in the template.

func TemplateFromText

func TemplateFromText(tmplText string, tmplData any, tmplName string) (string, error)

TemplateFromText renders the template 'tmplText' with data 'tmplData'. Parameter 'tmplName' is used for debugging purposes, a typical example is the template file name.

func UntarOne added in v0.3.3

func UntarOne(tarPath string, name string, dstPath string) error

UntarOne extracts file 'name' from tar file 'tarPath', expected to be compressed with gzip, and saves it to 'dstPath'.

Examples:

  • Flat archive, extract file "foo": UntarOne(tarPath, "foo", dst)
  • Hierarchical archive, extract file "bar/foo": UntarOne(tarPath, "bar/foo", dst)

func UnzipOne

func UnzipOne(zipPath string, name string, dstPath string) error

UnzipOne extracts file 'name' from ZIP file 'zipPath' and saves it to 'dstPath'.

func User

func User() *user.User

User returns the current user, as set by Init.

func UserAdd

func UserAdd(username string) error

Add user and create home directory. Do nothing if user already present. Password login is disabled (use SSH public key or use passwd)

func UserSystemAdd

func UserSystemAdd(username string, homedir string) error

UserSystemAdd adds the system user 'username' and group 'username', with home directory 'homedir' and mode 0o755.

func WriteFile

func WriteFile(fname string, data string, mode os.FileMode, owner string) error

WriteFile writes data to fname and sets the mode and owner of fname. If also creates any missing directories in the path, if any.

Types

type Config

type Config struct {
	// contains filtered or unexported fields
}

func NewConfig

func NewConfig(settingsPath string) (*Config, error)

func (*Config) Errors

func (cfg *Config) Errors() error

func (*Config) Get

func (cfg *Config) Get(k string) string

Get returns the value of key k if found. If the key is missing, it returns the empty string and adds the error to the list returned by Errors. This allows a simple sequence of calling Get multiple times and checking for all the keys that were missing keys only once at the end, by calling Errors.

If on the other end you want to know immediately if the key is missing, use Lookup.

func (*Config) Lookup

func (cfg *Config) Lookup(k string) (string, error)

Lookup returns the value of key k if found. If the key is missing, it returns an error. Contrary to Get, it does not append a lookup failure to the errors returned by Errors.

type Configurer

type Configurer interface {
	Configure() error
}

type Flower

type Flower interface {
	Installer
	Configurer
}

type Hash

type Hash int
const (
	SHA256 Hash = iota + 1
)

type Installer

type Installer interface {
	String() string
	Description() string
	Embedded() []string
	Init() error
	Install() error
}

type Options

type Options struct {
	// Output for the logger. Defaults to os.Stdout. Before changing to os.Stderr,
	// consider that HashiCorp Packer renders any output to stderr in red, thus
	// making everything look like an error.
	// The default log level is INFO; it can be changed to DEBUG via the --log-level
	// command-line flag.
	LogOutput io.Writer
	// Optimization to avoid refreshing the OS package manager cache each time before
	// installing an OS package. Defaults to DefOsPkgCacheValidity.
	OsPkgCacheValidity time.Duration
	// The setup function, called before any command-line subcommand. Mandatory.
	SetupFn func(prov *Provisioner) error
	// The preConfigure function, called before the command-line configure
	// subcommand. Mandatory.
	PreConfigureFn func(prov *Provisioner, config *Config) (any, error)
	// The postConfigure function, called after the command-line configure
	// subcommand. Optional.
	PostConfigureFn func(prov *Provisioner, config *Config, bag any) error
}

The Options passed to MainInt. For an example, see florist/example/main.go

type Provisioner

type Provisioner struct {
	// contains filtered or unexported fields
}

func (*Provisioner) AddFlowers

func (prov *Provisioner) AddFlowers(flowers ...Flower) error

func (*Provisioner) Flowers

func (prov *Provisioner) Flowers() map[string]Flower

Flowers returns

func (*Provisioner) UseWorkdir

func (prov *Provisioner) UseWorkdir()

FIXME what is this doing????

Jump to

Keyboard shortcuts

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