README

GoDoc Build Status codecov Go Report Card

gornir

Gornir is a pluggable framework with inventory management to help operate collections of devices. It's similar to nornir but in golang.

The goal is to be able to operate on many devices with little effort. For instance:

package main

import (
	"context"
	"os"

	"github.com/nornir-automation/gornir/pkg/gornir"
	"github.com/nornir-automation/gornir/pkg/plugins/connection"
	"github.com/nornir-automation/gornir/pkg/plugins/inventory"
	"github.com/nornir-automation/gornir/pkg/plugins/logger"
	"github.com/nornir-automation/gornir/pkg/plugins/output"
	"github.com/nornir-automation/gornir/pkg/plugins/runner"
	"github.com/nornir-automation/gornir/pkg/plugins/task"
)

func main() {
	log := logger.NewLogrus(false)

	file := "/go/src/github.com/nornir-automation/gornir/examples/hosts.yaml"
	plugin := inventory.FromYAML{HostsFile: file}
	inv, err := plugin.Create()
	if err != nil {
		log.Fatal(err)
	}

	gr := gornir.New().WithInventory(inv).WithLogger(log).WithRunner(runner.Parallel())

	// Open an SSH connection towards the devices
	results, err := gr.RunSync(
		context.Background(),
		&connection.SSHOpen{},
	)
	if err != nil {
		log.Fatal(err)
	}

	// defer closing the SSH connection we just opened
	defer func() {
		results, err = gr.RunSync(
			context.Background(),
			&connection.SSHClose{},
		)
		if err != nil {
			log.Fatal(err)
		}
	}()

	// Following call is going to execute the task over all the hosts using the runner.Parallel runner.
	// Said runner is going to handle the parallelization for us. Gornir.RunS is also going to block
	// until the runner has completed executing the task over all the hosts
	results, err = gr.RunSync(
		context.Background(),
		&task.RemoteCommand{Command: "ip addr | grep \\/24 | awk '{ print $2 }'"},
	)
	if err != nil {
		log.Fatal(err)
	}
	// next call is going to print the result on screen
	output.RenderResults(os.Stdout, results, "What is my ip?", true)
}

would render:

# What is my ip?
@ dev5.no_group
  - err: failed to retrieve connection: couldn't find connection

@ dev1.group_1
  - stdout: 10.21.33.101/24

  - stderr:
@ dev6.no_group
  - stdout: 10.21.33.106/24

  - stderr:
@ dev4.group_2
  - stdout: 10.21.33.104/24

  - stderr:
@ dev3.group_2
  - stdout: 10.21.33.103/24

  - stderr:
@ dev2.group_1
  - stdout: 10.21.33.102/24

  - stderr:

Examples

You can see more examples in the examples folder and run them with Docker-Compose as follows:

  1. Create a development enviroment
make start-dev-env
  1. Run any of the examples in the examples folder with make example. Specify the name of the example with EXAMPLE; for instance 2_simple_with_filter.
make example EXAMPLE=2_simple_with_filter
  1. After you are done, make sure you stop the development enviroment
make stop-dev-env

The project is still work in progress and feedback/help is welcomed.

Expand ▾ Collapse ▴

Documentation

Overview

    Package gornir provides a pluggable framework with inventory management to help operate collections of devices. It's similar to https://github.com/nornir-automation/nornir/ but in Go.

    The goal is to be able to operate on many devices with little effort. For instance:

    package main
    
    import (
    	"context"
    	"os"
    
    	"github.com/nornir-automation/gornir/pkg/gornir"
    	"github.com/nornir-automation/gornir/pkg/plugins/connection"
    	"github.com/nornir-automation/gornir/pkg/plugins/inventory"
    	"github.com/nornir-automation/gornir/pkg/plugins/logger"
    	"github.com/nornir-automation/gornir/pkg/plugins/output"
    	"github.com/nornir-automation/gornir/pkg/plugins/runner"
    	"github.com/nornir-automation/gornir/pkg/plugins/task"
    )
    
    func main() {
    	log := logger.NewLogrus(false)
    
    	file := "/go/src/github.com/nornir-automation/gornir/examples/hosts.yaml"
    	plugin := inventory.FromYAML{HostsFile: file}
    	inv, err := plugin.Create()
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	gr := gornir.New().WithInventory(inv).WithLogger(log).WithRunner(runner.Parallel())
    
    	results, err := gr.RunSync(
    		context.Background(),
    		&connection.SSHOpen{},
    	)
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	// defer closing the SSH connection we just opened
    	defer func() {
    		results, err = gr.RunSync(
    			context.Background(),
    			&connection.SSHClose{},
    		)
    		if err != nil {
    			log.Fatal(err)
    		}
    	}()
    
    	results, err = gr.RunSync(
    		context.Background(),
    		&task.RemoteCommand{Command: "ip addr | grep \\/24 | awk '{ print $2 }'"},
    	)
    	if err != nil {
    		log.Fatal(err)
    	}
    	output.RenderResults(os.Stdout, results, "What is my ip?", true)
    }
    

    would render:

    # What is my ip?
    @ dev5.no_group
      - err: failed to retrieve connection: couldn't find connection
    
    @ dev1.group_1
      - stdout: 10.21.33.101/24
    
      - stderr:
    @ dev6.no_group
      - stdout: 10.21.33.106/24
    
      - stderr:
    @ dev4.group_2
      - stdout: 10.21.33.104/24
    
      - stderr:
    @ dev3.group_2
      - stdout: 10.21.33.103/24
    
      - stderr:
    @ dev2.group_1
      - stdout: 10.21.33.102/24
    
      - stderr:
    

    You can see more examples here: https://github.com/nornir-automation/gornir/tree/master/examples

    Source Files

    Directories

    Path Synopsis
    examples
    1_simple
    this is the simplest example possible
    this is the simplest example possible
    1_simple_processor
    this example is similar to 1_simple but it uses processors to render the result instead
    this example is similar to 1_simple but it uses processors to render the result instead
    2_simple_with_filter
    Similar to the simple example but filtering the hosts
    Similar to the simple example but filtering the hosts
    2_simple_with_filter_bis
    Similar to the simple_with_filter but leveraging included filters
    Similar to the simple_with_filter but leveraging included filters
    3_grouped_simple
    Here is an example of how we can compose tasks
    Here is an example of how we can compose tasks
    4_advanced_1
    In this example we can see how we can call the runner asynchronously
    In this example we can see how we can call the runner asynchronously
    5_advanced_2
    In this example we can see how we can call the runner asynchronously and process the results without having to wait for all the hosts to complete
    In this example we can see how we can call the runner asynchronously and process the results without having to wait for all the hosts to complete
    6_custom_ssh_config
    this is the simplest example possible
    this is the simplest example possible
    pkg
    gornir
    Package gornir implements the core functionality and define the needed interfaces to integrate with the framework
    Package gornir implements the core functionality and define the needed interfaces to integrate with the framework
    plugins/connection
    Package connection implements various Connection plugins that can be run over Hosts
    Package connection implements various Connection plugins that can be run over Hosts
    plugins/filter
    Package filter provides a collection of gornir.FilterFunc
    Package filter provides a collection of gornir.FilterFunc
    plugins/inventory
    Package inventory implements various plugins to instantiate and populate a gornir.Inventor object
    Package inventory implements various plugins to instantiate and populate a gornir.Inventor object
    plugins/logger
    Package logger implements various plugins to log events
    Package logger implements various plugins to log events
    plugins/output
    Package output implements functions to help processing the results
    Package output implements functions to help processing the results
    plugins/processor
    Package processor implements plugins to process the task events and results
    Package processor implements plugins to process the task events and results
    plugins/runner
    Package runner implements various plugins that can be used to defined the strategy to execute tasks over hosts
    Package runner implements various plugins that can be used to defined the strategy to execute tasks over hosts
    plugins/task
    Package task implements various Task plugins that can be run over Hosts
    Package task implements various Task plugins that can be run over Hosts