func NewObservable(labels map[string]string, parent string) reconciler.Observable {
	return reconciler.Observable{
		Type: Type,
		Obj: Observable{
			Labels: labels,
			Parent: parent,
		},
	}
}
--------------------- Observables -------------------------------
NewObservable returns an observable object
package redis
import (
	"context"
	"fmt"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/redis/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"reflect"
	"sigs.k8s.io/controller-reconciler/pkg/reconciler"
	rmanager "sigs.k8s.io/controller-reconciler/pkg/reconciler/manager"
	"sigs.k8s.io/controller-reconciler/pkg/reconciler/manager/gcp"
	"strings"
)
const (
	Type      = "redis"
	UserAgent = "kcc/controller-manager"
)
type RsrcManager struct {
	name    string
	service *redis.Service
}
func Getter(ctx context.Context) func() (string, rmanager.Manager, error) {
	return func() (string, rmanager.Manager, error) {
		rm := &RsrcManager{}
		service, err := NewService(ctx)
		if err != nil {
			return Type, nil, err
		}
		rm.WithService(service).WithName(Type + "Mgr")
		return Type, rm, nil
	}
}
func NewRsrcManager(ctx context.Context, name string) (*RsrcManager, error) {
	rm := &RsrcManager{}
	service, err := NewService(ctx)
	if err != nil {
		return nil, err
	}
	rm.WithService(service).WithName(name)
	return rm, nil
}
func (rm *RsrcManager) WithName(v string) *RsrcManager {
	rm.name = v
	return rm
}
func (rm *RsrcManager) WithService(s *redis.Service) *RsrcManager {
	rm.service = s
	return rm
}
type Object struct {
	Redis      *redis.Instance
	Parent     string
	InstanceID string
}
func (o *Object) SetLabels(labels map[string]string) {
	o.Redis.Labels = gcp.CompliantLabelMap(labels)
}
func (o *Object) SetOwnerReferences(refs *metav1.OwnerReference) bool { return false }
func (o *Object) IsSameAs(a interface{}) bool {
	same := false
	e := a.(*Object)
	if e.Parent == o.Parent && e.InstanceID == o.InstanceID {
		same = true
	}
	return same
}
func (o *Object) GetName() string {
	return o.Redis.Name + "(" + o.Redis.DisplayName + ")"
}
type Observable struct {
	Labels map[string]string
	Parent string
}
func (o *Object) AsReconcilerObject() *reconciler.Object {
	return &reconciler.Object{
		Obj:       o,
		Lifecycle: reconciler.LifecycleManaged,
		Type:      Type,
	}
}
func GetParent(project, region string) (string, error) {
	var err error
	if project == "" {
		project, err = gcp.GetProjectFromMetadata()
		if err != nil {
			return "", err
		}
	}
	if region == "" {
		region, err = gcp.GetZoneFromMetadata()
		if err != nil {
			return "", err
		}
	}
	splits := strings.Split(region, "-")
	region = splits[0] + "-" + splits[1]
	parent := fmt.Sprintf("projects/%v/locations/%v", project, region)
	return parent, nil
}
func (rm *RsrcManager) ObservablesFromObjects(bag []reconciler.Object, labels map[string]string) []reconciler.Observable {
	var observables []reconciler.Observable
	for _, item := range bag {
		if item.Type != Type {
			continue
		}
		obj, ok := item.Obj.(*Object)
		if !ok {
			continue
		}
		observables = append(observables, NewObservable(labels, obj.Parent))
	}
	return observables
}
func CopyMutatedSpecFields(to *reconciler.Object, from *reconciler.Object) {
	e := to.Obj.(*Object).Redis
	o := from.Obj.(*Object).Redis
	if e.AlternativeLocationId == "" {
		e.AlternativeLocationId = o.AlternativeLocationId
	}
	if e.AuthorizedNetwork == "" {
		e.AuthorizedNetwork = o.AuthorizedNetwork
	}
	if e.RedisVersion == "" {
		e.RedisVersion = o.RedisVersion
	}
	if e.ReservedIpRange == "" {
		e.ReservedIpRange = o.ReservedIpRange
	}
	if e.Tier == "" {
		e.Tier = o.Tier
	}
}
func (rm *RsrcManager) SpecDiffers(expected, observed *reconciler.Object) bool {
	CopyMutatedSpecFields(expected, observed)
	e := expected.Obj.(*Object).Redis
	o := observed.Obj.(*Object).Redis
	return !reflect.DeepEqual(e.AlternativeLocationId, o.AlternativeLocationId) ||
		!reflect.DeepEqual(e.AuthorizedNetwork, o.AuthorizedNetwork) ||
		!reflect.DeepEqual(e.DisplayName, o.DisplayName) ||
		!reflect.DeepEqual(e.Labels, o.Labels) ||
		!reflect.DeepEqual(e.MemorySizeGb, o.MemorySizeGb) ||
		!reflect.DeepEqual(e.RedisConfigs, o.RedisConfigs) ||
		!reflect.DeepEqual(e.RedisVersion, o.RedisVersion) ||
		!reflect.DeepEqual(e.ReservedIpRange, o.ReservedIpRange) ||
		!reflect.DeepEqual(e.Tier, o.Tier)
}
func (rm *RsrcManager) Observe(observables ...reconciler.Observable) ([]reconciler.Object, error) {
	var returnval []reconciler.Object
	for _, item := range observables {
		obs, ok := item.Obj.(Observable)
		if !ok {
			continue
		}
		redisList, err := rm.service.Projects.Locations.Instances.List(obs.Parent).Do()
		if err != nil {
			if gcp.IsNotFound(err) {
				continue
			}
			return []reconciler.Object{}, nil
		}
		for _, r := range redisList.Instances {
			obj := Object{Redis: r, Parent: obs.Parent}
			returnval = append(returnval, *obj.AsReconcilerObject())
		}
	}
	return returnval, nil
}
func (rm *RsrcManager) Update(item reconciler.Object) error {
	obj := item.Obj.(*Object)
	d := obj.Redis
	_, err := rm.service.Projects.Locations.Instances.Patch(obj.Parent+"/instances/"+obj.InstanceID, d).UpdateMask("displayName,labels,memorySizeGb,redisConfigs").Do()
	return err
}
func (rm *RsrcManager) Create(item reconciler.Object) error {
	obj := item.Obj.(*Object)
	d := obj.Redis
	_, err := rm.service.Projects.Locations.Instances.Create(obj.Parent, d).InstanceId(obj.InstanceID).Do()
	return err
}
func (rm *RsrcManager) List(parent string) ([]*redis.Instance, error) {
	lst, err := rm.service.Projects.Locations.Instances.List(parent).Do()
	return lst.Instances, err
}
func (rm *RsrcManager) Delete(item reconciler.Object) error {
	obj := item.Obj.(*Object)
	_, err := rm.service.Projects.Locations.Instances.Delete(obj.Parent + "/instances/" + obj.InstanceID).Do()
	return err
}
func NewObject(parent, instanceid string) (*reconciler.Object, error) {
	obj := &Object{
		Redis:      &redis.Instance{},
		InstanceID: instanceid,
		Parent:     parent,
	}
	return obj.AsReconcilerObject(), nil
}
func NewService(ctx context.Context) (*redis.Service, error) {
	httpClient, err := google.DefaultClient(ctx, redis.CloudPlatformScope)
	if err != nil {
		return nil, err
	}
	client, err := redis.New(httpClient)
	if err != nil {
		return nil, err
	}
	client.UserAgent = UserAgent
	return client, nil
}