func (c Controller) ResourceUpdated(oldR, newR *unstructured.Unstructured) {
	metrics.TotalEvents.Inc()
	c.logger.Infow("resource updated", "resource", newR.GetName())
	out, err := c.apply(newR)
	if err != nil {
		c.logger.Errorw("failed to update resource", "resource", newR.GetName(), "error", err, "cmdOutput", out)
		metrics.UpdateFailures.Inc()
		return
	}
	metrics.UpdatedReleases.Inc()
	metrics.LastSuccessfulUpdate.Set(float64(time.Now().UTC().UnixNano()) / 1000000000)
}
ResourceUpdated is called when a custom resource is updated or during a
resync and will generate the template files and apply them to Kubernetes
package tmplctlr
import (
	"io/ioutil"
	"os"
	"path/filepath"
	"time"
	"go.uber.org/zap"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"github.com/lostromos/lostromos/metrics"
	"github.com/lostromos/lostromos/tmpl"
)
type Controller struct {
	templatePath string      
	Client       KubeClient  
	logger       *zap.SugaredLogger
}
func NewController(tmplDir string, kubeCfg string, logger *zap.SugaredLogger) *Controller {
	if logger == nil {
		logger = zap.NewNop().Sugar()
	}
	c := &Controller{
		Client:       &Kubectl{ConfigFile: kubeCfg},
		templatePath: filepath.Join(tmplDir, "*.tmpl"),
		logger:       logger,
	}
	return c
}
func (c Controller) ResourceAdded(r *unstructured.Unstructured) {
	metrics.TotalEvents.Inc()
	c.logger.Infow("resource added", "resource", r.GetName())
	out, err := c.apply(r)
	if err != nil {
		c.logger.Errorw("failed to add resource", "resource", r.GetName(), "error", err, "cmdOutput", out)
		metrics.CreateFailures.Inc()
		return
	}
	metrics.CreatedReleases.Inc()
	metrics.ManagedReleases.Inc()
	metrics.LastSuccessfulCreate.Set(float64(time.Now().UTC().UnixNano()) / 1000000000)
}