func mkPointer(val reflect.Value) interface{} {
	if val.Kind() == reflect.Ptr {
		return val.Interface()
	}
	if val.CanAddr() {
		return val.Addr().Interface()
	}
	if val.Kind() == reflect.Struct {
		nv := reflect.New(val.Type())
		nv.Elem().Set(val)
		return nv.Interface()
	}
	return val.Interface()
}
if i is a pointer, just return the value.
if i is addressable, return that.
if i is a struct passed in by value, make a new instance of the type and copy the contents to that and return
the pointer to that.
package controllerutils
import (
	"reflect"
	"github.com/solo-io/skv2/pkg/equalityutils"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
)
func ObjectsEqual(obj1, obj2 runtime.Object) bool {
	value1, value2 := reflect.ValueOf(obj1), reflect.ValueOf(obj2)
	if value1.Type() != value2.Type() {
		return false
	}
	if value1.Kind() == reflect.Ptr {
		value1 = value1.Elem()
		value2 = value2.Elem()
	}
	if meta1, hasMeta := obj1.(metav1.Object); hasMeta {
		if !ObjectMetasEqual(meta1, obj2.(metav1.Object)) {
			return false
		}
	}
	for i := 0; i < value1.NumField(); i++ {
		field1Name := value1.Type().Field(i).Name
		if field1Name == "ObjectMeta" {
			continue
		}
		if field1Name == "TypeMeta" {
			continue
		}
		if field1Name == "Status" {
			continue
		}
		field1 := mkPointer(value1.Field(i))
		field2 := mkPointer(value2.Field(i))
		if !equalityutils.DeepEqual(field1, field2) {
			return false
		}
	}
	return true
}