func wrapDestroyFunc(c *TestContext, tag string, nodes []Gravity, destroy func(context.Context) error) DestroyFn {
	return func() error {
		defer func() {
			if r := recover(); r != nil {
				c.Logger().WithFields(
					logrus.Fields{
						"stack": string(debug.Stack()),
						"where": r,
					},
				).Error("Panic in terraform destroy.")
			}
		}()
		log := c.Logger().WithFields(logrus.Fields{
			"nodes":              nodes,
			"provisioner_policy": policy,
			"test_status":        testStatus[c.Failed()],
		})
		skipLogCollection := false
		ctx := c.Context()
		if ctx.Err() != nil && !policy.DestroyOnFailure {
			log.WithError(ctx.Err()).Info("Skipping destroy.")
			return trace.Wrap(ctx.Err())
		}
		if ctx.Err() != nil {
			skipLogCollection = true
		}
		if !skipLogCollection && (c.Failed() || policy.AlwaysCollectLogs) {
			log.Debug("Collecting logs from nodes...")
			err := c.CollectLogs("postmortem", nodes)
			if err != nil {
				log.WithError(err).Warn("Failed to collect logs from at least one node.")
			}
		}
		if !policy.DestroyOnSuccess ||
			(c.Failed() && !policy.DestroyOnFailure) {
			log.Info("not destroying VMs per policy")
			return nil
		}
		c.monitorCancel()
		log.Info("Destroying VMs.")
		err := destroyResource(destroy)
		if err != nil {
			log.WithError(err).Error("Failed to destroy VM resources.")
		} else {
			if errDestroy := resourceDestroyed(tag); errDestroy != nil {
				log.WithError(errDestroy).Warn("Failed to remove resource account.")
			}
		}
		return trace.Wrap(err)
	}
}
wrapDestroyFunc returns a function that wraps the specified set of nodes
and the given clean up function that implements report collection and resource clean up.
package gravity
import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"runtime/debug"
	"sync"
	"time"
	"github.com/gravitational/robotest/infra"
	"github.com/gravitational/robotest/infra/providers/gce"
	"github.com/gravitational/robotest/infra/terraform"
	"github.com/gravitational/robotest/lib/constants"
	"github.com/gravitational/robotest/lib/defaults"
	"github.com/gravitational/robotest/lib/wait"
	"github.com/gravitational/trace"
	"github.com/sirupsen/logrus"
)
type DestroyFn func() error
type ProvisionerPolicy struct {
	DestroyOnSuccess bool
	DestroyOnFailure bool
	AlwaysCollectLogs bool
	ResourceListFile string
}
var policy ProvisionerPolicy
func SetProvisionerPolicy(p ProvisionerPolicy) {
	policy = p
}
var testStatus = map[bool]string{true: "failed", false: "ok"}
const finalTeardownTimeout = 20 * time.Minute