I wanted to practice a bit Go programing, so I divided that task in two parts, one, adding a golang extension for Citellus and a sample, but working plugin using it.

If interested in the code it’s available at the review at https://review.gerrithub.io/c/citellusorg/citellus/+/495622.

The final sample code for it has been:

// Author: Pablo Iranzo Gómez ([email protected])
// Header for citellus metadata
// long_name: Report detected number of CPU's
// description: List the processors detected in the system
// priority: 200

package main

import (
	"bufio"
	"io"
	"os"
	"runtime"
	"strconv"
	"strings"
)

func main() {
	var OKAY, _ = strconv.Atoi(os.Getenv("RC_OKAY"))
	var SKIP, _ = strconv.Atoi(os.Getenv("RC_SKIPPED"))
	var INFO, _ = strconv.Atoi(os.Getenv("RC_INFO"))
	var CITELLUS_ROOT = os.Getenv("CITELLUS_ROOT")
	var CITELLUS_LIVE, _ = strconv.Atoi(os.Getenv("CITELLUS_LIVE"))
	var FAILED, _ = strconv.Atoi(os.Getenv("RC_FAILED"))
	if CITELLUS_LIVE == 1 {
		// Report # of CPU's
		var CPUS = runtime.NumCPU()
		os.Stderr.WriteString(strconv.Itoa(CPUS))
		os.Exit(INFO)
	} else if CITELLUS_LIVE == 0 {
		file, err := os.Open(CITELLUS_ROOT + "/proc/cpuinfo")
		if err != nil {
			os.Stderr.WriteString("Failure to open required file " + CITELLUS_ROOT + "/proc/cpuinfo")
			os.Exit(SKIP)
		}
		defer file.Close()
		counts := wordCount(file)
		os.Stderr.WriteString(strconv.Itoa(counts["processor"]))
		os.Exit(INFO)
	} else {
		os.Stderr.WriteString("Undefined CITELLUS_LIVE status")
		os.Exit(FAILED)
	}
	// Failback case, exiting as OK
	os.Exit(OKAY)
}

// https://forgetcode.com/go/2348-count-the-number-of-word-occurrence-in-given-a-file
func wordCount(rdr io.Reader) map[string]int {
	counts := map[string]int{}
	scanner := bufio.NewScanner(rdr)
	scanner.Split(bufio.ScanWords)
	for scanner.Scan() {
		word := scanner.Text()
		word = strings.ToLower(word)
		counts[word]++
	}
	return counts
}

Of course, lot of googling helped to start building the pieces.

Things to have in consideration:

  • Go programs are compiled so it requires being compiled with go build XXX or executed with go run XXX
  • Programs executed with go run XXX might face some issues, as return code is not honoured (you can find more information on this).
  • As program needs to be compiled, it will take a while to compile before execution (but still is fast)
  • Undefined variables will make the program compilation to fail.
  • Variable types are checked, so expect to use conversion when reading values, etc to have it compiling and working.

For the citellus specifics:

  • In above example, we use Citellus Return Codes as defined in the citellus guidelines, but when executed with go run XXX only standard error codes are returned
  • As citellus metadata parser gets it from headers, an update to the default function was done so that the comment character can be defined, in case of Go programs it is: // citellus then takes it into consideration for the offsets to grab the data.

Happy coding!