info_tfgrid/collections/developers/internals/zos/development/testing.md
2024-05-13 19:10:10 -04:00

3.9 KiB

Testing

Beside unit testing, you might want to test your change in an integrated environment, the following are two options to do it.

Using grid/node client

You can simply use any grid client to deploy a workload of any type, you should specify your node's twin ID (and make sure you are on the correct network).

Inside the node, you can do noded -id and noded -net to get your current node ID and network. Also, you can check your farm and get node information from there.

Another option is the golang node client.

While deploying on your local node, logs with zinit log would be helpful to see any possible errors and to debug your code.

Using a test app

If you need to test a specific module or functionality, you can create a simple test app inside e.g. tools directory.

Inside this simple test app, you can import any module or talk to another one using zbus.

An example to talk to container and qsfs modules

// tools/del/main.go

package main

import (
	"context"
	"flag"
	"strings"
	"time"

	"github.com/rs/zerolog"
	"github.com/rs/zerolog/log"

	"github.com/threefoldtech/zbus"
	"github.com/threefoldtech/zos/pkg"
	"github.com/threefoldtech/zos/pkg/stubs"
)

func main() {
	zerolog.SetGlobalLevel(zerolog.DebugLevel)

	zbus, err := zbus.NewRedisClient("unix:///var/run/redis.sock")
	if err != nil {
		log.Err(err).Msg("cannot init zbus client")
		return
	}

	var workloadType, workloadID string

	flag.StringVar(&workloadType, "type", "", "workload type (qsfs or container)")
	flag.StringVar(&workloadID, "id", "", "workload ID")

	flag.Parse()

	if workloadType == "" || workloadID == "" {
		log.Error().Msg("you need to provide both type and id")
		return
	}

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	if workloadType == "qsfs" {
		qsfsd := stubs.NewQSFSDStub(zbus)
		err := qsfsd.SignalDelete(ctx, workloadID)
		if err != nil {
			log.Err(err).Msg("cannot delete qsfs workload")
		}
	} else if workloadType == "container" {
		args := strings.Split(workloadID, ":")
		if len(args) != 2 {
			log.Error().Msg("container id must contain namespace, e.g. qsfs:wl129")
		}

		containerd := stubs.NewContainerModuleStub(zbus)
		err := containerd.SignalDelete(ctx, args[0], pkg.ContainerID(args[1]))
		if err != nil {
			log.Err(err).Msg("cannot delete container workload")
		}
	}

}

Then we can simply build, upload and execute this in our node:

cd tools/del
go build
scp del root@192.168.123.44:/root/del

Then ssh into 192.168.123.44 and simply execute your test app:

./del

An example of directly using zinit package

// tools/zinit_test
package main

import (
	"encoding/json"
	"fmt"
	"regexp"

	"github.com/rs/zerolog"
	"github.com/rs/zerolog/log"

	"github.com/threefoldtech/zos/pkg/zinit"
)

func main() {
	zerolog.SetGlobalLevel(zerolog.DebugLevel)
	z := zinit.New("/var/run/zinit.sock")

	regex := fmt.Sprintf(`^ip netns exec %s %s`, "ndmz", "/sbin/udhcpc")
	_, err := regexp.Compile(regex)
	if err != nil {
		log.Err(err).Msgf("cannot compile %s", regex)
		return
	}

	// try match
	matched, err := z.Matches(zinit.WithExecRegex(regex))
	if err != nil {
		log.Err(err).Msg("cannot filter services")
	}

	matchedStr, err := json.Marshal(matched)
	if err != nil {
		log.Err(err).Msg("cannot convert matched map to json")
	}

	log.Debug().Str("matched", string(matchedStr)).Msg("matched services")

	// // try destroy
	// err = z.Destroy(10*time.Second, matched...)
	// if err != nil {
	// 	log.Err(err).Msg("cannot destroy matched services")
	// }
}