From de8d8300b08fedd9d68cd0c1973e9e4193336dcc Mon Sep 17 00:00:00 2001 From: Fabio Forni Date: Sat, 4 Nov 2023 14:19:07 +0100 Subject: [PATCH] service: Document --- service/service.go | 82 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 12 deletions(-) diff --git a/service/service.go b/service/service.go index a29f089..dace80f 100644 --- a/service/service.go +++ b/service/service.go @@ -25,21 +25,54 @@ const ( ) var ( + // DefaultPkgManager is the default package manager command to install OS packages. DefaultPkgManager = []string{"pkcon", "install", "-y"} ) +// Service is a collection of resources to reinstall/restore on an operating system. +// All fields except Name are optional. type Service struct { - Name string `yaml:"-"` - Depends *DepSet `yaml:"depends"` - Setup *string `yaml:"setup"` - PkgManager []string `yaml:"pkgmanager"` - Packages []string `yaml:"packages"` - Links map[string]FilePath `yaml:"links"` - Variables map[string]VarValue `yaml:"variables"` - Copies map[string]FilePath `yaml:"copies"` - Finalize *string `yaml:"finalize"` + // Name uniquely identifies a Service. + Name string `yaml:"-"` + + // Depends is a set of Service names upon which this Service depends. + Depends *DepSet `yaml:"depends"` + + // Setup is a script (UNIX Shell or Powershell, depending on the operating system) + // to run before reinstalling and/or restoring any resources. + Setup *string `yaml:"setup"` + + // PkgManager is combination of command name + // and arguments to reinstall operating system packages. + // It must accept a list of package names appended to it. + PkgManager []string `yaml:"pkgmanager"` + + // Packages is a list of operating system packages to reinstall. + // It will be appended as-is to PkgManager. + Packages []string `yaml:"packages"` + + // Links is a collection of symlinks to restore. Their source path + // is relative to Service's linkdir. + Links map[string]FilePath `yaml:"links"` + + // Variables is a collection of local variables associated to this Service. + // A template engine may use them to edit files in place before copying them, + // or to customize Setup and Finalize scripts. + // Variables will always contain at least VarDatadir of Datadir kind. + Variables map[string]VarValue `yaml:"variables"` + + // Copies is a collection of files to copy. Their source path + // is relative to Service's datadir. A template engine may use Variables + // to customize the content. + Copies map[string]FilePath `yaml:"copies"` + + // Setup is a script (UNIX Shell or Powershell, depending on the operating system) + // to run after reinstalling and/or restoring any resources. + Finalize *string `yaml:"finalize"` } +// New creates a Service with a given name. Variables will contain VarDatadir +// and PkgManager will be DefaultPkgManager. func New(name string) *Service { return &Service{ Name: name, @@ -50,11 +83,15 @@ func New(name string) *Service { } } +// NewFromYAML creates a Service with a given name whose fields are defined by +// a buffered YAML document. func NewFromYAML(name string, yml []byte) (*Service, error) { srv := New(name) return srv, yaml.Unmarshal(yml, srv) } +// NewFromYAML creates a Service with a given name whose fields are defined by +// a streaming YAML document. func NewFromYAMLReader(name string, rd io.Reader) (*Service, error) { srv := New(name) err := yaml.NewDecoder(rd).Decode(srv) @@ -64,26 +101,33 @@ func NewFromYAMLReader(name string, rd io.Reader) (*Service, error) { return srv, err } +// Hash returns a string that uniquely identifies this Service. +// It currently returns Name. func (srv *Service) Hash() string { return srv.Name } +// DepSet is an unordered set of Service names. type DepSet struct { *set.Set[string] } +// NewDepSet crates an empty DepSet with an initial capacity. func NewDepSet(capacity int) DepSet { return DepSet{set.New[string](capacity)} } +// NewDepSetFrom creates a DepSet from a list of Service names. func NewDepSetFrom(items []string) DepSet { return DepSet{set.From(items)} } +// Equal returns true if ds is equal to ds2. func (ds DepSet) Equal(ds2 DepSet) bool { return ds.Set.Equal(ds2.Set) } +// UnmarshalYAML implements the yaml.Unmarshaler interface. func (ds *DepSet) UnmarshalYAML(node *yaml.Node) error { var deps []string err := node.Decode(&deps) @@ -94,11 +138,14 @@ func (ds *DepSet) UnmarshalYAML(node *yaml.Node) error { return nil } +// FilePath is a filesystem file path with its file mode. type FilePath struct { Path string `yaml:"path"` Mode uint16 `yaml:"mode"` } +// UnmarshalYAML implements the yaml.Unmarshaler interface. +// Mode defaults to 0644 if unspecified in the YAML node. func (lp *FilePath) UnmarshalYAML(node *yaml.Node) error { switch node.Kind { case yaml.ScalarNode: @@ -121,18 +168,29 @@ func (lp *FilePath) UnmarshalYAML(node *yaml.Node) error { return nil } +// VarKind is a kind of variable. +// Any non-ClearText kind will require a solver to extract the value. type VarKind string const ( + // ClearText is the simplest VarKind. Any variable of type ClearText + // has its value immediately accessible. ClearText VarKind = "cleartext" - Datadir VarKind = "datadir" + + // Datadir is the path of a Service's data directory. + Datadir VarKind = "datadir" ) +// VarValue is a variable's value. type VarValue struct { - Kind VarKind `yaml:"kind"` - Value string `yaml:"value"` + // Kind is the variable kind. Unless it's ClearText, a solver is required + // to get the real value. + Kind VarKind `yaml:"kind"` + // Value is either the final value, if Kind is ClearText, or an intermediate value. + Value string `yaml:"value"` } +// UnmarshalYAML implements the yaml.Unmarshaler interface. func (val *VarValue) UnmarshalYAML(node *yaml.Node) error { switch node.Kind { case yaml.ScalarNode: