Repository: crossplane/crossplane-runtime (go)

Issue:
resource references only support string fields

### What happened?
Some terraform providers, such as the [Linode](https://registry.terraform.io/providers/linode/linode/latest/docs/resources/instance) provider use resource IDs that are not strings and are instead of type [int](https://github.com/linode/terraform-provider-linode/blob/dev/linode/instance/schema_resource.go). This causes an issue when trying to create references between resources because the [FromPtrValue](https://github.com/crossplane/crossplane-runtime/blob/master/pkg/reference/reference.go#L46-L51) and [ToPtrValue](https://github.com/crossplane/crossplane-runtime/blob/master/pkg/reference/reference.go#L54-L59) only support strings for references. 


### How can we reproduce it?
I have reproduced this issue in this repository where you can see the issue [here](https://github.com/eljohnson92/provider-linode/blob/incorrect_machine_id/apis/instance/v1alpha1/zz_generated.resolvers.go#L41). it is possible to overwrite the terraform schema for parts of the codebase to be a string instead of an int, but it does cause some problems when reconciling external resources so if it were possible for these functions to just support int/float references as well as strings. 

I am happy to try and contribute a fix to have ToPtrValue and ForPtrValue support more types if that is what is needed but please let me know if I might be missing something or if there is a more appropriate place to fix this issue.

### What environment did it happen in?

crossplane version: [v0.19.0-rc.0](https://github.com/crossplane/crossplane-runtime/releases/tag/v0.19.0-rc.0)
upjet version: [v0.7.0](https://github.com/upbound/upjet/releases/tag/v0.7.0)



Pull request description:
add support for float pointer references
### Description of your changes
This change allows for types of references that are not strings. some terraform providers use "number" types for resource IDs which seem to get translated to float64 as part of upjet. when trying to use them as references previously only strings were supported, this PR along with a PR in crossplane-tools allows for "number" IDs to also be supported as references

Fixes #366 

I have:

- [ x ] Read and followed Crossplane's [contribution process].
- [ x ] Run `make reviewable test` to ensure this PR is ready for review.

### How has this code been tested

This has been tested by adding unit tests to cover the new functions, and this code has also been tested by the [linode-provider](https://github.com/linode/provider-linode), which is using my forked version of this repo and the crossplane-tools repo



Patch:
diff --git a/pkg/reference/reference.go b/pkg/reference/reference.go
index 971c728..90818e1 100644
--- a/pkg/reference/reference.go
+++ b/pkg/reference/reference.go
@@ -18,6 +18,7 @@ package reference
 
 import (
 	"context"
+	"strconv"
 
 	kerrors "k8s.io/apimachinery/pkg/api/errors"
 
@@ -50,6 +51,14 @@ func FromPtrValue(v *string) string {
 	return *v
 }
 
+// FromFloatPtrValue adapts a float pointer field for use as a CurrentValue.
+func FromFloatPtrValue(v *float64) string {
+	if v == nil {
+		return ""
+	}
+	return strconv.FormatFloat(*v, 'f', 0, 64)
+}
+
 // ToPtrValue adapts a ResolvedValue for use as a string pointer field.
 func ToPtrValue(v string) *string {
 	if v == "" {
@@ -58,6 +67,18 @@ func ToPtrValue(v string) *string {
 	return &v
 }
 
+// ToFloatPtrValue adapts a ResolvedValue for use as a float64 pointer field.
+func ToFloatPtrValue(v string) *float64 {
+	if v == "" {
+		return nil
+	}
+	vParsed, err := strconv.ParseFloat(v, 64)
+	if err != nil {
+		return nil
+	}
+	return &vParsed
+}
+
 // FromPtrValues adapts a slice of string pointer fields for use as CurrentValues.
 // NOTE: Do not use this utility function unless you have to.
 // Using pointer slices does not adhere to our current API practices.
@@ -71,6 +92,15 @@ func FromPtrValues(v []*string) []string {
 	return res
 }
 
+// FromFloatPtrValues adapts a slice of float64 pointer fields for use as CurrentValues.
+func FromFloatPtrValues(v []*float64) []string {
+	var res = make([]string, len(v))
+	for i := 0; i < len(v); i++ {
+		res[i] = FromFloatPtrValue(v[i])
+	}
+	return res
+}
+
 // ToPtrValues adapts ResolvedValues for use as a slice of string pointer fields.
 // NOTE: Do not use this utility function unless you have to.
 // Using pointer slices does not adhere to our current API practices.
@@ -84,6 +114,15 @@ func ToPtrValues(v []string) []*string {
 	return res
 }
 
+// ToFloatPtrValues adapts ResolvedValues for use as a slice of float64 pointer fields.
+func ToFloatPtrValues(v []string) []*float64 {
+	var res = make([]*float64, len(v))
+	for i := 0; i < len(v); i++ {
+		res[i] = ToFloatPtrValue(v[i])
+	}
+	return res
+}
+
 // To indicates the kind of managed resource a reference is to.
 type To struct {
 	Managed resource.Managed


Test patch:
diff --git a/pkg/reference/reference_test.go b/pkg/reference/reference_test.go
index 27ba361..99f1a17 100644
--- a/pkg/reference/reference_test.go
+++ b/pkg/reference/reference_test.go
@@ -66,6 +66,25 @@ func TestToAndFromPtr(t *testing.T) {
 	}
 }
 
+func TestToAndFromFloatPtr(t *testing.T) {
+	cases := map[string]struct {
+		want string
+	}{
+		"Zero":    {want: ""},
+		"NonZero": {want: "1123581321"},
+	}
+	for name, tc := range cases {
+		t.Run(name, func(t *testing.T) {
+			got := FromFloatPtrValue(ToFloatPtrValue(tc.want))
+			if diff := cmp.Diff(tc.want, got); diff != "" {
+				t.Errorf("FromPtrValue(ToPtrValue(%s): -want, +got: %s", tc.want, diff)
+
+			}
+		})
+
+	}
+}
+
 func TestToAndFromPtrValues(t *testing.T) {
 	cases := map[string]struct {
 		want []string
@@ -86,6 +105,26 @@ func TestToAndFromPtrValues(t *testing.T) {
 	}
 }
 
+func TestToAndFromFloatPtrValues(t *testing.T) {
+	cases := map[string]struct {
+		want []string
+	}{
+		"Nil":      {want: []string{}},
+		"Zero":     {want: []string{""}},
+		"NonZero":  {want: []string{"1123581321"}},
+		"Multiple": {want: []string{"1123581321", "1234567890"}},
+	}
+	for name, tc := range cases {
+		t.Run(name, func(t *testing.T) {
+			got := FromFloatPtrValues(ToFloatPtrValues(tc.want))
+			if diff := cmp.Diff(tc.want, got); diff != "" {
+				t.Errorf("FromPtrValues(ToPtrValues(%s): -want, +got: %s", tc.want, diff)
+
+			}
+		})
+	}
+}
+
 func TestResolve(t *testing.T) {
 	errBoom := errors.New("boom")
 	now := metav1.Now()