### Example puppet.conf configuration Source: https://github.com/purpleidea/mgmt/blob/master/docs/puppet-guide.md An example of a puppet.conf file that can be used with the --puppet-conf option to set main section configurations. ```puppet [main] server=mgmt-master.example.net vardir=/var/lib/mgmt/puppet ``` -------------------------------- ### Info Method Example (No Unification Variables) Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md An example implementation of the Info method for a function with a simple signature. ```golang func (obj *FooFunc) Info() *interfaces.Info { return &interfaces.Info{ Sig: types.NewType("func(a str, b int) float"), } } ``` -------------------------------- ### Info Method Example (With Unification Variables) Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md An example implementation of the Info method for a function using unification variables in its signature. ```golang func (obj *FooFunc) Info() *interfaces.Info { return &interfaces.Info{ Sig: types.NewType("func(a ?1, b ?2, foo [?3]) ?1"), } } ``` -------------------------------- ### Remote Module Import Example Source: https://github.com/purpleidea/mgmt/blob/master/docs/style-guide.md Demonstrates how to import a remote module, showing the default namespacing and how to specify a custom namespace. ```go import "https://github.com/purpleidea/mgmt-banana/" import "https://github.com/purpleidea/mgmt-banana/" as tomato ``` -------------------------------- ### Go Godoc Comment Example Source: https://github.com/purpleidea/mgmt/blob/master/docs/style-guide.md Demonstrates the correct format for Go documentation comments (godoc) which must start with the function name and end with a period if it's a full sentence. It also shows an inline comment explaining a specific implementation detail. ```go // square multiplies the input integer by itself and returns this product. func square(x int) int { return x * x // we don't care about overflow errors } ``` -------------------------------- ### Simple Function Implementation Example Source: https://github.com/purpleidea/mgmt/blob/master/docs/function-guide.md Demonstrates how to implement a simple function using the `simple.Scaffold` in Go. This function takes an integer, squares it, and returns the result as a formatted string. It highlights type declaration, argument extraction, and return value formatting. ```golang package simple import ( "context" "fmt" "github.com/purpleidea/mgmt/lang/funcs/simple" "github.com/purpleidea/mgmt/lang/types" ) // you must register your functions in init when the program starts up func init() { // Example function that squares an int and prints out answer as an str. simple.ModuleRegister(ModuleName, "talkingsquare", &simple.Scaffold{ T: types.NewType("func(int) str"), // declare the signature F: func(ctx context.Context, input []types.Value) (types.Value, error) { i := input[0].Int() // get first arg as an int64 // must return the above specified value return &types.StrValue{ V: fmt.Sprintf("%d^2 is %d", i, i * i), }, }, }) } ``` -------------------------------- ### Resource Struct Example Source: https://github.com/purpleidea/mgmt/blob/master/docs/resource-guide.md Demonstrates the structure of a resource in mgmt, including anonymous trait references, initialization pointers, public API fields with struct tags, and private fields. ```go type FooRes struct { traits.Base // add the base methods without re-implementation traits.Groupable traits.Refreshable init *engine.Init Whatever string `lang:"whatever" yaml:"whatever"` // you pick! Baz bool `lang:"baz" yaml:"baz"` // something else something string // some private field } ``` -------------------------------- ### Polymorphic Function Registration Example Source: https://github.com/purpleidea/mgmt/blob/master/docs/function-guide.md Shows how to register a function with multiple polymorphic forms using the `simple.Register` function. This example defines a 'len' function that can accept different input types (string, slice, map) and return an integer, demonstrating type matching for polymorphism. ```golang package simple import ( "context" "fmt" "github.com/purpleidea/mgmt/lang/funcs/simple" "github.com/purpleidea/mgmt/lang/types" ) func init() { // This is the actual definition of the `len` function. simple.Register("len", &simple.Scaffold{ T: types.NewType("func(?1) int"), // contains a unification var C: simple.TypeMatch([]string{ // match on any of these sigs "func(str) int", "func([]?1) int", "func(map{?1: ?2}) int", }), // The implementation is left as an exercise for the reader. F: Len, }) } ``` -------------------------------- ### Run a Simple mgmt Example Source: https://github.com/purpleidea/mgmt/blob/master/docs/quick-start-guide.md Executes a basic 'hello world' example using the mgmt runtime. If mgmt was built from source, use './mgmt' instead of 'mgmt'. Press Ctrl+C to exit. ```shell mgmt run --tmp-prefix lang examples/lang/hello0.mcl ``` -------------------------------- ### Custom YAML Unmarshalling Example Source: https://github.com/purpleidea/mgmt/blob/master/docs/resource-guide.md Provides an example implementation of the UnmarshalYAML method for a FooRes struct. This demonstrates how to handle defaults, avoid recursion, and correctly unmarshal YAML data into the resource struct. ```golang // UnmarshalYAML is the custom unmarshal handler for this struct. It is // primarily useful for setting the defaults. func (obj *FooRes) UnmarshalYAML(unmarshal func(interface{}) error) error { type rawRes FooRes // indirection to avoid infinite recursion def := obj.Default() // get the default res, ok := def.(*FooRes) // put in the right format if !ok { return fmt.Errorf("could not convert to FooRes") } raw := rawRes(*res) // convert; the defaults go here if err := unmarshal(&raw); err != nil { return err } *obj = FooRes(raw) // restore from indirection with type conversion! return nil } ``` -------------------------------- ### Install Puppet Module Source: https://github.com/purpleidea/mgmt/blob/master/docs/puppet-guide.md Installs the necessary 'ffrank-mgmtgraph' Puppet module using the puppet module command. This module is required on the machine running 'mgmt'. ```bash puppet module install ffrank-mgmtgraph ``` -------------------------------- ### Mgmt Function Struct Example Source: https://github.com/purpleidea/mgmt/blob/master/docs/function-guide.md Illustrates the structure of a function, typically using a pointer receiver and a 'Func' suffix for naming conventions. This struct holds necessary initialization data. ```golang type FooFunc struct { init *interfaces.Init // this space can be used if needed } ``` -------------------------------- ### Golang CheckApply Method Implementation Example Source: https://github.com/purpleidea/mgmt/blob/master/docs/resource-guide.md Demonstrates how to implement the CheckApply method in Golang, showing a pattern for splitting check and apply logic within a single method. This pattern is useful for managing shared state or resources between check and apply operations. ```golang func (obj *FooRes) CheckApply(ctx context.Context, apply bool) (bool, error) { // my private split implementation of check and apply if c, err := obj.check(ctx); err != nil { return false, err // we errored } else if c { return true, nil // state was good! } if !apply { return false, nil // state needs fixing, but apply is false } err := obj.apply(ctx) // errors if failure or unable to apply return false, err // always return false, with an optional error } ``` -------------------------------- ### Install System and Go Dependencies Source: https://github.com/purpleidea/mgmt/blob/master/docs/quick-start-guide.md Installs necessary system and Go dependencies for building the mgmt project. The specific actions are detailed in misc/make-deps.sh. ```shell make deps ``` -------------------------------- ### Golang Function Generator Example Source: https://github.com/purpleidea/mgmt/blob/master/docs/function-guide.md Demonstrates how to use a function generator in Golang to create multiple `FuncValue` implementations from a single generator. This technique aids in code reuse by allowing the generator to accept inputs and build individual functions with unique signatures. ```golang package main import ( "fmt" types "github.com/purpleidea/mgmt/types" ) // Generator function that creates a specific math.fortytwo function func fortytwoGenerator() func([]types.Value) (types.Value, error) { return func(args []types.Value) (types.Value, error) { // This function always returns the integer 42 return types.NewValue(42), } } func main() { // Get the specific function implementation from the generator fortytwoFunc := fortytwoGenerator() // Call the function result, err := fortytwoFunc([]types.Value{}) // No arguments needed for math.fortytwo if err != nil { fmt.Printf("Error executing function: %v\n", err) } else { fmt.Printf("Result: %v (Type: %s)\n", result.Interface(), result.Type()) } } ``` -------------------------------- ### Mixed Graph: Multiple Merges (puppet) Source: https://github.com/purpleidea/mgmt/blob/master/docs/puppet-guide.md Example of Puppet code demonstrating how to set up multiple merge points using classes prefixed with 'mgmt_' to interact with mcl's 'noop' resources. ```puppet # puppet class mgmt_handover {} include mgmt_handover class mgmt_handback {} include mgmt_handback file { "/tmp/puppet_dir": ensure => "directory" } file { "/tmp/puppet_dir/a": ensure => "file" } file { "/tmp/puppet_dir/puppet_subtree/state-file": ensure => "file" } File["/tmp/puppet_dir/a"] -> Class["mgmt_handover"] Class["mgmt_handback"] -> File["/tmp/puppet_dir/puppet_subtree/state-file"] ``` -------------------------------- ### Install Golang on macOS using Homebrew Source: https://github.com/purpleidea/mgmt/blob/master/docs/quick-start-guide.md Installs the Golang development environment on macOS using the Homebrew package manager. ```shell brew install go ``` -------------------------------- ### Golang Module Import Recommendation Source: https://github.com/purpleidea/mgmt/blob/master/docs/style-guide.md Illustrates the recommended way to import Go modules to avoid naming conflicts with core packages. ```go import "golang/strings" as golang_strings ``` -------------------------------- ### Install Golang on RPM-based Systems Source: https://github.com/purpleidea/mgmt/blob/master/docs/quick-start-guide.md Installs the Golang development environment on systems that use DNF package manager, such as Fedora. ```shell sudo dnf install golang ``` -------------------------------- ### Go Method Receiver Pointer Convention Source: https://github.com/purpleidea/mgmt/blob/master/docs/style-guide.md Illustrates the preferred Go convention of using pointer receivers for methods. The example shows a correctly implemented method with a pointer receiver and an incorrectly implemented one without. ```go type Foo struct { Whatever string // ... } // Bar is implemented correctly as a pointer on Foo. func (obj *Foo) Bar(baz string) int { // ... } // Bar is implemented *incorrectly* without a pointer to Foo. func (obj Foo) Bar(baz string) int { // ... } ``` -------------------------------- ### Dollar Metaparam Example Source: https://github.com/purpleidea/mgmt/blob/master/docs/documentation.md Demonstrates the use of the 'Dollar' metaparameter to allow resource names starting with a '$' sign. It shows how to correctly interpolate variables using curly braces. ```mcl $foo = "/tmp/file1" file "$foo" {} # incorrect! $foo = "/tmp/file1" file "${foo}" {} # correct! ``` -------------------------------- ### Init Resource Initialization Source: https://github.com/purpleidea/mgmt/blob/master/docs/resource-guide.md Initializes a resource by setting up necessary components like channels and sync primitives. It accepts an initialization struct containing useful data and pointers from the engine. Errors during initialization should be returned. ```golang Init() error // Init initializes the Foo resource. func (obj *FooRes) Init(init *engine.Init) error { obj.init = init // save for later // run the resource specific initialization, and error if anything fails if some_error { return err // something went wrong! } return nil } ``` -------------------------------- ### Install Golang on APT-based Systems Source: https://github.com/purpleidea/mgmt/blob/master/docs/quick-start-guide.md Installs the Golang development environment on systems that use APT package manager, such as Debian or Ubuntu. ```shell sudo apt install golang ``` -------------------------------- ### Resource Registration Source: https://github.com/purpleidea/mgmt/blob/master/docs/resource-guide.md This code snippet demonstrates how to register a resource with the engine. The init function is a special Go method that runs once, and it's used here to set the resource kind and struct. ```golang func init() { // set your resource kind and struct here (the kind must be lower case) engine.RegisterResource("foo", func() engine.Res { return &FooRes{} }) } ``` -------------------------------- ### Mixed Graph: Multiple Merges (mcl) Source: https://github.com/purpleidea/mgmt/blob/master/docs/puppet-guide.md Example of mcl code with multiple 'noop' resources prefixed by 'puppet_' to facilitate multiple merge points with Puppet code. ```mcl # lang noop "puppet_handover" {} noop "puppet_handback" {} file "/tmp/mgmt_dir/" { state => "present" } file "/tmp/mgmt_dir/a" { state => "present" } file "/tmp/mgmt_dir/puppet_subtree/state-file" { state => "present" } File["/tmp/mgmt_dir/"] -> Noop["puppet_handover"] Noop["puppet_handback"] -> File["/tmp/mgmt_dir/puppet_subtree/state-file"] ``` -------------------------------- ### Mixed Graph: Merged Vertex (mcl) Source: https://github.com/purpleidea/mgmt/blob/master/docs/puppet-guide.md Example of mcl code including a 'noop' resource with a name prefixed by 'puppet_' to enable merging with Puppet resources. ```mcl # lang noop "puppet_handover_to_mgmt" {} file "/tmp/mgmt_dir/" { state => "present" } file "/tmp/mgmt_dir/a" { state => "present" } Noop["puppet_handover_to_mgmt"] -> File["/tmp/mgmt_dir/"] ``` -------------------------------- ### MCL Meta Parameters Example Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md Demonstrates how to specify meta parameters in MCL, including direct assignment and using a struct. Supports elvis operator for conditional assignment. ```mcl file "/tmp/f1" { content => "hello!\n", Meta:noop => true, Meta:delay => $b ?: 42, Meta:autoedge => false, } ``` ```mcl file "/tmp/f1" { content => "hello!\n", Meta => $b ?: struct{ noop => false, retry => -1, delay => 0, poll => 5, limit => 4.2, burst => 3, sema => ["foo:1", "bar:3",], autoedge => true, autogroup => false, }, } ``` -------------------------------- ### Sending Values with Send() Source: https://github.com/purpleidea/mgmt/blob/master/docs/resource-guide.md Illustrates how to send data using the obj.init.Send() method within the CheckApply function. This is used to propagate values to destinations, and the example shows sending an ExecSends struct containing output and error streams. ```golang // inside CheckApply, somewhere near the end usually if err := obj.init.Send(&ExecSends{ // send the special data structure Output: obj.output, Stdout: obj.stdout, Stderr: obj.stderr, }); err != nil { return false, err } ``` -------------------------------- ### Class Definition Syntax Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md Shows how to define a class, which binds a list of statements to a name. Classes can be parameterized. ```mcl class foo { # some statements go here } or class bar($a, $b) { # a parameterized class # some statements go here } ``` -------------------------------- ### Go Method Receiver Naming Convention Source: https://github.com/purpleidea/mgmt/blob/master/docs/style-guide.md Shows the convention of naming method receivers 'obj' for consistency and ease of code review. This example demonstrates a method using 'obj' as the receiver name. ```go // Bar does a thing, and returns the number of baz results found in our // database. func (obj *Foo) Bar(baz string) int { if len(obj.s) > 0 { return strings.Count(obj.s, baz) } return -1 } ``` -------------------------------- ### Init Method Signature and Parameters Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md The Init method is called by the function graph engine to create an implementation of the function, receiving initialization parameters. ```golang type Init struct { Hostname string // uuid for the host Input chan types.Value // Engine will close `input` chan Output chan types.Value // Stream must close `output` chan World resources.World Debug bool Logf func(format string, v ...interface{}) } Init(*Init) error ``` -------------------------------- ### Configure Puppet with custom puppet.conf Source: https://github.com/purpleidea/mgmt/blob/master/docs/puppet-guide.md Specifies a custom puppet.conf file for mgmt to use, allowing control over Puppet's runtime options like servername and certname. ```bash mgmt run puppet --puppet /opt/my-manifest.pp --puppet-conf /etc/mgmt/puppet.conf ``` -------------------------------- ### Mgmt Function Registration Source: https://github.com/purpleidea/mgmt/blob/master/docs/function-guide.md Demonstrates how to register functions with the mgmt engine using `funcs.Register` for standalone functions or `funcs.ModuleRegister` for functions within modules. This ensures functions are discoverable and encodable. ```golang import "github.com/purpleidea/mgmt/lang/funcs" func init() { // special golang method that runs once funcs.Register("foo", func() interfaces.Func { return &FooFunc{} }) } ``` ```golang // moduleName is already set to "math" by the math package. Do this in `init`. funcs.ModuleRegister(moduleName, "cos", func() interfaces.Func { return &CosFunc{} }) ``` -------------------------------- ### Resource Watch Functionality Source: https://github.com/purpleidea/mgmt/blob/master/docs/resource-guide.md Implements the main loop for a resource, handling events, errors, and shutdown signals. It sets up the resource, notifies the engine of its running status, and processes events from the resource's internal mechanisms. ```golang // Watch is the listener and main loop for this resource. func (obj *FooRes) Watch(ctx.Context) error { // setup the Foo resource var err error if err, obj.foo = OpenFoo(); err != nil { return err // we couldn't startup } defer obj.whatever.CloseFoo() // shutdown our Foo // notify engine that we're running obj.init.Running() // when started, notify engine that we're running for { select { // the actual events! case event := <-obj.foo.Events: if !is_an_event { continue // skip event } // send below... // event errors case err := <-obj.foo.Errors: return err // will cause a retry or permanent failure case <-ctx.Done(): // signal for shutdown request return nil } obj.init.Event() // notify engine of an event (this can block) } } ``` -------------------------------- ### Empty Slice Declarations in Go Source: https://github.com/purpleidea/mgmt/blob/master/docs/style-guide.md Illustrates three common ways to declare an empty slice in Go, recommending the first method for its conciseness and readability. ```golang 1. a := []string{} 2. var a []string 3. a := make([]string, 0) ``` -------------------------------- ### Func API Interface Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md Defines the core interface for built-in functions. Requires implementing Info, Init, and Stream methods. ```APIDOC Func Interface: Info() *Info Returns information about the function, including its signature. Init(*Init) error Initializes the function with engine-provided resources and channels. Stream(context.Context) error Handles input processing and output production for the function. ``` -------------------------------- ### mgmt Resource Methods API Source: https://github.com/purpleidea/mgmt/blob/master/docs/resource-guide.md Defines the core methods for managing resources within the mgmt framework. These include initialization, cleanup, and state reconciliation. ```APIDOC Resource Methods: Init() error - Purpose: Initializes the resource, setting up internal components like channels and sync primitives. - Input: An initialization struct containing engine-provided data and pointers. - Output: An error if initialization fails. - Notes: Called after Validate. Should handle resource-specific setup. Cleanup() error - Purpose: Cleans up resources, such as closing persistent connections. - Output: An error if cleanup fails. - Notes: Not a shutdown signal; for releasing resources opened in Init. CheckApply(ctx context.Context, apply bool) (checkOK bool, err error) - Purpose: Checks and applies resource state changes. - Parameters: - ctx: Context for monitoring shutdown or timeouts. - apply: If true, apply changes; if false, operate in noop mode. - Output: - checkOK: True if the state is already correct, false otherwise. - err: An error if state reconciliation fails. - Notes: Must converge the resource in a single execution. If state is incorrect and apply is false, return (false, nil). Engine may skip calls if state is not invalidated. ``` -------------------------------- ### Puppet Classes and Dependencies Source: https://github.com/purpleidea/mgmt/blob/master/docs/puppet-guide.md Defines Puppet classes for management handover and handback, and establishes their execution order using resource ordering. It also includes a class that manages a directory resource. ```puppet class mgmt_handover {} class mgmt_handback {} include mgmt_handover, mgmt_handback class important_stuff { file { "/tmp/mgmt_dir/puppet_subtree": ensure => "directory" } # ... } Class["mgmt_handover"] -> Class["important_stuff"] -> Class["mgmt_handback"] ``` -------------------------------- ### Build mgmt using Docker Source: https://github.com/purpleidea/mgmt/blob/master/docs/quick-start-guide.md Builds a Docker image for mgmt and then extracts the mgmt binary from the container. This method avoids installing build dependencies directly on the host system. ```shell git clone --recursive https://github.com/purpleidea/mgmt/ cd mgmt docker build -t mgmt -f docker/Dockerfile . docker run --rm --entrypoint cat mgmt mgmt > mgmt chmod +x mgmt ./mgmt --version ``` -------------------------------- ### Puppet Resource Default for File Type Source: https://github.com/purpleidea/mgmt/blob/master/docs/puppet-guide.md Demonstrates using a resource default in Puppet to set 'backup => false' for all File resources, simplifying manifests and avoiding warnings. ```puppet File { backup => false } ``` -------------------------------- ### Variable Reuse in Go Source: https://github.com/purpleidea/mgmt/blob/master/docs/style-guide.md Demonstrates preferred methods for handling string manipulation in Go to avoid unnecessary variable reuse, promoting cleaner and more maintainable code. ```golang MyNotIdealFunc(s string, b bool) string { if !b { return s + "hey" } s = strings.Replace(s, "blah", "", -1) // not ideal (reuse of `s` var) return s } MyOkayFunc(s string, b bool) string { if !b { return s + "hey" } s2 := strings.Replace(s, "blah", "", -1) // doesn't reuse `s` variable return s2 } MyGreatFunc(s string, b bool) string { if !b { return s + "hey" } return strings.Replace(s, "blah", "", -1) // even cleaner } ``` -------------------------------- ### Resource API: Default Method Source: https://github.com/purpleidea/mgmt/blob/master/docs/resource-guide.md Implements the Default method for a resource, returning a populated resource struct with sensible defaults. It's preferred to use Go's zero values where possible. ```go // Default returns some sensible defaults for this resource. func (obj *FooRes) Default() engine.Res { return &FooRes{ Answer: 42, // sometimes, defaults shouldn't be the zero value } } ``` -------------------------------- ### Nested Class Definition Example Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md Provides an example of nested class definitions within MCL, including an import statement and conditional inclusion of a nested class. ```mcl import "fmt" class c1($a, $b) { # nested class definition class c2($c) { test $a { stringptr => fmt.printf("%s is %d", $b, $c), } } if $a == "t1" { include c2(42) } } ``` -------------------------------- ### Receiving Sent Values with Recv() Source: https://github.com/purpleidea/mgmt/blob/master/docs/resource-guide.md Demonstrates how to check for received values within the CheckApply function using the obj.init.Recv() method. It shows how to access received keys, check if they have changed, and log relevant information. ```golang // inside CheckApply, probably near the top if val, exists := obj.init.Recv()["some_key"]; exists { obj.init.Logf("the some_key param was sent to us from: %s.%s", val.Res, val.Key) if val.Changed { obj.init.Logf("the some_key param was just updated!") // you may want to invalidate some local cache } } ``` -------------------------------- ### Puppet File Resource with Default Backup Behavior Source: https://github.com/purpleidea/mgmt/blob/master/docs/puppet-guide.md Shows a Puppet file resource that triggers a warning because it uses the default 'puppet' file bucket, which mgmt cannot handle. It illustrates the need to explicitly disable backups. ```puppet puppet mgmtgraph print --code 'file { "/tmp/mgmt-test": }' ``` -------------------------------- ### Mixed Graph: Merged Vertex (puppet) Source: https://github.com/purpleidea/mgmt/blob/master/docs/puppet-guide.md Example of Puppet code including an empty class with a name prefixed by 'mgmt_' to enable merging with mcl resources. ```puppet # puppet class mgmt_handover_to_mgmt {} include mgmt_handover_to_mgmt file { "/tmp/puppet_dir": ensure => "directory" } file { "/tmp/puppet_dir/a": ensure => "file" } File["/tmp/puppet_dir/a"] -> Class["mgmt_handover_to_mgmt"] ``` -------------------------------- ### FOSDEM 2024 Golang Devroom Video Source: https://github.com/purpleidea/mgmt/blob/master/docs/on-the-web.md A video recording from the FOSDEM 2024 Golang Devroom, discussing single binary full-stack provisioning. ```video Recording from FOSDEM 2024, Golang Devroom https://video.fosdem.org/2024/ud2218a/fosdem-2024-2575-single-binary-full-stack-provisioning.mp4 ``` -------------------------------- ### If Expression Example Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md Demonstrates the usage of an 'if' expression in the mcl language. An 'if' expression requires both 'then' and 'else' branches, each containing a single expression, and returns the value of the executed branch. ```mcl $b = true $x = if $b { 42 } else { -13 } ``` -------------------------------- ### If Statement Example Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md Illustrates an 'if' statement in the mcl language. An 'if' statement can have one or two branches containing statements, and does not return a value but produces output like resources and edges. ```mcl $b = true if $b { file "/tmp/hello" { content => "world", } } ``` -------------------------------- ### Contributing to mgmt (Golang) Source: https://github.com/purpleidea/mgmt/blob/master/docs/faq.md Steps for individuals who want to contribute Golang code to the mgmt project. This includes setting up a GNU/Linux environment, basic Git familiarity, completing the Golang tour, joining the IRC channel, and finding issues tagged with #mgmtlove. ```english 1. Set up a recent GNU/Linux environment (Fedora or Debian recommended). 2. Be comfortable with Git basics. 3. Complete the Golang tour (focus on overview). 4. Join the #mgmtconfig IRC channel on Libera.Chat. 5. Find and contribute to issues tagged #mgmtlove. ``` -------------------------------- ### Puppet Support in mgmt Source: https://github.com/purpleidea/mgmt/blob/master/docs/documentation.md Demonstrates how to use Puppet manifests with the mgmt tool. This includes requesting configurations from a puppet server, compiling local manifest files, and compiling ad hoc manifests from the command line. ```bash mgmt run puppet --puppet agent mgmt run puppet --puppet /path/to/my/manifest.pp mgmt run puppet --puppet 'file { "/etc/ntp.conf": ensure => file }' ``` -------------------------------- ### mgmt Language Types Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md This section details the fundamental data types supported by the mgmt language. It covers basic types like bool, str, int, and float, as well as composite types such as lists, maps, structs, and functions. The descriptions include examples and internal Golang representations where applicable. ```mgmt bool: true or false str: "string!" int: 42 or -13 (internal: int64) float: 3.1415926 (internal: float64) list: [6, 7, 8, 9,] map: {"boiling" => 100, "freezing" => 0} struct: struct{answer => "42", james => "awesome"} func: func(s str) int or func(bool, []str, {str: float}) struct{foo str; bar int} ``` -------------------------------- ### Mgmt Configuration Language: Class and Include Blog Post Source: https://github.com/purpleidea/mgmt/blob/master/docs/on-the-web.md This blog post discusses the 'Class' and 'Include' features within the Mgmt Configuration Language, explaining their usage and benefits for organizing configurations. ```blog Mgmt Configuration Language: Class and Include https://purpleidea.com/blog/2019/07/26/class-and-include-in-mgmt/ ``` -------------------------------- ### Emacs Lisp Package Installation Source: https://github.com/purpleidea/mgmt/blob/master/misc/emacs/README.md Instructions for installing the mgmtconfig-mode Emacs package via MELPA. This involves enabling MELPA and then searching for and installing the package through Emacs' package management interface. ```emacs-lisp ;; Add MELPA to your init.el if not already present ;; (require 'package) ;; (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) ;; (package-initialize) ;; Then, in Emacs: ;; M-x package-refresh-contents ;; M-x package-install RET mgmtconfig-mode RET ``` -------------------------------- ### Contributing to mgmt (Non-Golang) Source: https://github.com/purpleidea/mgmt/blob/master/docs/faq.md Guidance for contributing to the mgmt project without writing Golang code. This includes using and testing the tool, writing documentation, promoting the project, and learning the mgmt DSL. ```english Contribute by using, testing, writing docs, or promoting the project. Consider learning the mgmt DSL for automation module development. ``` -------------------------------- ### Build mgmt from Source Source: https://github.com/purpleidea/mgmt/blob/master/docs/quick-start-guide.md Compiles the mgmt project from its source code, producing a binary executable. This command should be run from the root of the mgmt project directory. ```shell make ``` -------------------------------- ### Golang Tour Reference Source: https://github.com/purpleidea/mgmt/blob/master/docs/faq.md A reference to the official Golang tour for learning the language, recommended as a prerequisite for contributing Golang code to the mgmt project. ```golang // Golang Tour: https://tour.golang.org/ ``` -------------------------------- ### Resolving PackageKit Dependency Errors Source: https://github.com/purpleidea/mgmt/blob/master/docs/faq.md Provides solutions for the "The name is not activatable" error when using the `pkg` resource, which indicates that PackageKit is not installed or configured correctly. It suggests installing `pkcon` on Fedora or `packagekit-tools` on Debian. ```bash # Fedora dnf install /usr/bin/pkcon ``` ```bash # Debian apt install packagekit-tools ``` -------------------------------- ### For Loop Syntax Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md Illustrates the syntax for a for loop, which iterates over a list. It provides access to both the index and the value of each element. ```mcl $list = ["a", "b", "c",] for $index, $value in $list { # some statements go here } ``` -------------------------------- ### CheckApply Resource State Management Source: https://github.com/purpleidea/mgmt/blob/master/docs/resource-guide.md Checks if the resource's state is correct. If `apply` is true, it attempts to reconcile the state. If `apply` is false, it operates in noop mode. The context should be monitored for shutdown signals. It must converge the resource in a single execution or return an error. ```golang CheckApply(ctx context.Context, apply bool) (checkOK bool, err error) // CheckApply does the idempotent work of checking and applying resource state. func (obj *FooRes) CheckApply(ctx context.Context, apply bool) (bool, error) { // check the state if state_is_okay { return true, nil } // done early! :) // state was bad if !apply { return false, nil } // don't apply, we're in noop mode if any_error { return false, err } // anytime there's an err! // do the apply! return false, nil // after success applying } ``` -------------------------------- ### Info Method Signature Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md The Info method must return a struct containing information about the function, specifically its signature. ```golang type Info struct { Sig *types.Type // the signature of the function, must be KindFunc } Info() *Info ``` -------------------------------- ### Resource Interface: Default Source: https://github.com/purpleidea/mgmt/blob/master/docs/resource-guide.md The signature for the Default method within the mgmt Resource interface. It returns a populated resource struct. ```APIDOC Default() engine.Res // This returns a populated resource struct as a Res. It shouldn't populate any values which already get a good default as the respective golang zero value. In general it is preferable if the zero values make for the correct defaults. (This is to say, resources are designed to behave safely and intuitively when parameters take a zero value, whenever this is possible.) ``` -------------------------------- ### Handling Shared Library Errors (`.so` files) Source: https://github.com/purpleidea/mgmt/blob/master/docs/faq.md Offers solutions for errors like "cannot open shared object file: No such file or directory" related to missing `.so` files for Augeas and libvirt. It suggests either building mgmt without these features or installing the development dependencies. ```bash # Build without features GOTAGS="noaugeas novirt nodocker" make build ``` ```bash # Fedora dependencies dnf install libvirt-devel augeas-devel ``` ```bash # Debian dependencies apt install libvirt-dev libaugeas-dev ``` -------------------------------- ### Edge Statement Syntax Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md Demonstrates the syntax for an edge statement, which defines relationships between resources, forming a directed acyclic graph. ```mcl File["/tmp/hello"] -> Print["alert4"] ``` -------------------------------- ### Clone mgmt Repository and Dependencies Source: https://github.com/purpleidea/mgmt/blob/master/docs/quick-start-guide.md Clones the mgmt source code recursively to ensure all submodules are included, and then switches to the project directory. It also adds the Go binary path to the system's PATH environment variable. ```shell git clone --recursive https://github.com/purpleidea/mgmt/ ~/mgmt/ cd ~/mgmt/ export PATH=$PATH:$GOPATH/bin ``` -------------------------------- ### If Statement Syntax Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md Demonstrates the syntax for an if statement, including the optional else branch. It takes a conditional expression and a block of statements. ```mcl if { } else { # the else branch is optional for if statements } ``` -------------------------------- ### MCL Language Indentation Source: https://github.com/purpleidea/mgmt/blob/master/docs/style-guide.md Specifies that code indentation in the MCL language should be done using tabs, with a recommended tab-width of eight. ```mcl Code indentation is done with tabs. The tab-width is a private preference, which is the beauty of using tabs: you can have your own personal preference. The inventor of `mgmt` uses and recommends a width of eight, and that is what should be used if your tool requires a modeline to be publicly committed. ``` -------------------------------- ### Function Engine Initialization and Validation Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md Details the process of initializing the function engine with function implementations and information. It emphasizes the type-checking phase to ensure data flow compatibility, preventing issues like passing an `int` where a `bool` is expected. ```go type FunctionEngine struct { FunctionRegistry map[string]FunctionImplementation // ... other fields } type FunctionImplementation interface { Signature() FunctionSignature Execute(args map[string]interface{}) (interface{}, error) } type FunctionSignature struct { Name string Parameters map[string]Type ReturnType Type } func NewFunctionEngine(functions []FunctionImplementation) (*FunctionEngine, error) { engine := &FunctionEngine{ FunctionRegistry: make(map[string]FunctionImplementation), } for _, fn := range functions { engine.FunctionRegistry[fn.Signature().Name] = fn } // Perform initial type checking of the function registry if err := engine.validateFunctionSignatures(); err != nil { return nil, err } return engine, nil } func (fe *FunctionEngine) validateFunctionSignatures() error { // Implement logic to check if function signatures are consistent and valid // For example, check for duplicate function names, parameter type compatibility, etc. return nil } ``` -------------------------------- ### Lexing and Parsing with LexParse Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md Lexing is performed using nex, a pure-golang lexer generator similar to Lex/Flex. Parsing is handled by goyacc, Go's implementation of yacc. The `LexParse` method integrates both lexing and parsing processes. ```golang package main import ( "fmt" "github.com/blynn/nex" ) // Assuming LexParse is a method that combines lexing and parsing func main() { // Example usage of LexParse (actual implementation not provided in text) // lexer := nex.NewLexer(inputString) // ast, err := LexParse(lexer) // if err != nil { // fmt.Printf("Error during lexing/parsing: %v\n", err) // return // } // fmt.Printf("Parsed AST: %+v\n", ast) fmt.Println("Lexing and parsing functionality demonstration.") } ``` -------------------------------- ### Naked Class Definition Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md Demonstrates the definition of a naked class in MCL, which is a grouping structure that binds statements to a name without parameters. ```mcl class foo { # some statements go here } ``` -------------------------------- ### Puppet File Resource with Unsupported Attribute Source: https://github.com/purpleidea/mgmt/blob/master/docs/puppet-guide.md Demonstrates a Puppet file resource with an unsupported attribute ('mode') that will be ignored by mgmt, resulting in a warning. ```puppet puppet mgmtgraph print --code 'file { "/tmp/foo": mode => "0600" }' ``` -------------------------------- ### Virt Resource Source: https://github.com/purpleidea/mgmt/blob/master/docs/resources.md Manages virtual machines using libvirt. ```APIDOC ## Virt The virt resource can manage virtual machines via libvirt. ``` -------------------------------- ### FOSDEM 2019 Virtualization Devroom Video Source: https://github.com/purpleidea/mgmt/blob/master/docs/on-the-web.md A video recording from the FOSDEM 2019 Virtualization Devroom, focusing on real-time virtualization automation. ```video Recording from FOSDEM Virtualization Devroom 2019 https://video.fosdem.org/2019/H.2213/vai_real_time_virtualization_automation.webm ``` -------------------------------- ### Mgmt DSL Introduction Source: https://github.com/purpleidea/mgmt/blob/master/docs/faq.md Information about the mgmt configuration language, described as a small DSL rather than a general-purpose programming language, making it potentially more enjoyable for automation module development. ```english // Mgmt Configuration Language: https://purpleidea.com/blog/2018/02/05/mgmt-configuration-language/ // A small DSL, potentially more fun for automation than general-purpose languages. ``` -------------------------------- ### Parameterized Class Definition (Inferred Types) Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md Shows how to define a parameterized class in MCL where the argument types are inferred by the type unification algorithm. ```mcl class bar($a, $b) { # some statements go here } ``` -------------------------------- ### Include Class with Variable Export Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md Demonstrates how to include a class and access its exported variables. The 'as' keyword is used to alias the included class. ```mcl import "fmt" class c1 { test "t1" {} # gets pulled out $x = "hello" # gets exported } include c1 as i1 test "print0" { anotherstr => fmt.printf("%s", $i1.x), # hello onlyshow => ["AnotherStr",] # displays nicer } ``` -------------------------------- ### Forkv Loop Syntax Source: https://github.com/purpleidea/mgmt/blob/master/docs/language-guide.md Shows the syntax for a forkv loop, designed for iterating over a map. It provides access to both the key and the value of each map entry. ```mcl $map = {0 => "a", 1 => "b", 2 => "c",} forkv $key, $val in $map { # some statements go here } ``` -------------------------------- ### Mgmt Configuration Language: Functions Blog Post Source: https://github.com/purpleidea/mgmt/blob/master/docs/on-the-web.md This blog post delves into the implementation and usage of functions within the Mgmt Configuration Language, highlighting how they enhance code reusability and logic. ```blog Mgmt Configuration Language: Functions https://purpleidea.com/blog/2024/11/22/functions-in-mgmt/ ``` -------------------------------- ### Mixed Graph: No Merges (mcl and puppet) Source: https://github.com/purpleidea/mgmt/blob/master/docs/puppet-guide.md Demonstrates creating two separate subgraphs by providing mcl and puppet inputs without any merging resources. ```puppet # puppet file { "/tmp/puppet_dir": ensure => "directory" } file { "/tmp/puppet_dir/a": ensure => "file" } ``` -------------------------------- ### Mixed Graph: No Merges (mcl and puppet) Source: https://github.com/purpleidea/mgmt/blob/master/docs/puppet-guide.md Demonstrates creating two separate subgraphs by providing mcl and puppet inputs without any merging resources. ```mcl # lang file "/tmp/mgmt_dir/" { state => "present" } file "/tmp/mgmt_dir/a" { state => "present" } ``` -------------------------------- ### Resource Interface: Validate Source: https://github.com/purpleidea/mgmt/blob/master/docs/resource-guide.md The signature for the Validate method within the mgmt Resource interface. It checks the validity of the resource struct and returns an error if invalid. ```APIDOC Validate() error // This method is used to validate if the populated resource struct is a valid representation of the resource kind. If it does not conform to the resource specifications, it should return an error. If you notice that this method is quite large, it might be an indication that you should reconsider the parameter list and interface to this resource. This method is called by the engine _before_ `Init`. It can also be called occasionally after a Send/Recv operation to verify that the newly populated parameters are valid. Remember not to expect access to the outside world when using this. ``` -------------------------------- ### Nspawn Resource Source: https://github.com/purpleidea/mgmt/blob/master/docs/resources.md Manages systemd-machined style containers. ```APIDOC ## Nspawn The nspawn resource is used to manage systemd-machined style containers. ``` -------------------------------- ### Cleanup Resource Cleanup Source: https://github.com/purpleidea/mgmt/blob/master/docs/resource-guide.md Cleans up resources after they are no longer needed, such as closing persistent connections opened during initialization. This is not a shutdown signal but a method for releasing resources. ```golang Cleanup() error // Cleanup is run by the engine to clean up after the resource is done. func (obj *FooRes) Cleanup() error { err := obj.conn.Close() // close some internal connection obj.someMap = nil // free up some large data structure from memory return err } ```