Skip to content

Commit 67ef84e

Browse files
committed
feat: add AddReference method to References
Signed-off-by: Yordis Prieto <[email protected]>
1 parent 4073347 commit 67ef84e

File tree

2 files changed

+142
-95
lines changed

2 files changed

+142
-95
lines changed

pkg/config/resource.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,26 @@ type ExternalName struct {
165165
IdentifierFields []string
166166
}
167167

168+
var ErrReferenceAlreadyExists = errors.New("reference for field already exists")
169+
168170
// References represents reference resolver configurations for the fields of a
169171
// given resource. Key should be the field path of the field to be referenced.
170172
type References map[string]Reference
171173

174+
// AddReference adds a reference configuration for the given field path.
175+
// The fieldPath is the Terraform field path of the field to be referenced.
176+
//
177+
// Example: "vpc_id" or "forwarding_rule.certificate_name" in case of nested
178+
// in another object.
179+
func (r References) AddReference(fieldPath string, ref Reference) error {
180+
if _, ok := r[fieldPath]; ok {
181+
return ErrReferenceAlreadyExists
182+
}
183+
184+
r[fieldPath] = ref
185+
return nil
186+
}
187+
172188
// Reference represents the Crossplane options used to generate
173189
// reference resolvers for fields
174190
type Reference struct {

pkg/config/resource_test.go

Lines changed: 126 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -5,110 +5,141 @@
55
package config
66

77
import (
8-
"context"
9-
"fmt"
10-
"testing"
8+
"context"
9+
"errors"
10+
"fmt"
11+
"testing"
1112

12-
"github.com/crossplane/crossplane-runtime/pkg/errors"
13-
"github.com/crossplane/crossplane-runtime/pkg/fieldpath"
14-
xpresource "github.com/crossplane/crossplane-runtime/pkg/resource"
15-
"github.com/crossplane/crossplane-runtime/pkg/resource/fake"
16-
"github.com/crossplane/crossplane-runtime/pkg/test"
17-
"github.com/google/go-cmp/cmp"
18-
"sigs.k8s.io/controller-runtime/pkg/client"
13+
"github.com/crossplane/crossplane-runtime/pkg/fieldpath"
14+
xpresource "github.com/crossplane/crossplane-runtime/pkg/resource"
15+
"github.com/crossplane/crossplane-runtime/pkg/resource/fake"
16+
"github.com/crossplane/crossplane-runtime/pkg/test"
17+
"github.com/google/go-cmp/cmp"
18+
"sigs.k8s.io/controller-runtime/pkg/client"
1919
)
2020

2121
const (
22-
kind = "ACoolService"
23-
name = "example-service"
24-
provider = "ACoolProvider"
22+
kind = "ACoolService"
23+
name = "example-service"
24+
provider = "ACoolProvider"
2525
)
2626

2727
func TestTagger_Initialize(t *testing.T) {
28-
errBoom := errors.New("boom")
28+
errBoom := errors.New("boom")
2929

30-
type args struct {
31-
mg xpresource.Managed
32-
kube client.Client
33-
}
34-
type want struct {
35-
err error
36-
}
37-
cases := map[string]struct {
38-
args
39-
want
40-
}{
41-
"Successful": {
42-
args: args{
43-
mg: &fake.Managed{},
44-
kube: &test.MockClient{MockUpdate: test.NewMockUpdateFn(nil)},
45-
},
46-
want: want{
47-
err: nil,
48-
},
49-
},
50-
"Failure": {
51-
args: args{
52-
mg: &fake.Managed{},
53-
kube: &test.MockClient{MockUpdate: test.NewMockUpdateFn(errBoom)},
54-
},
55-
want: want{
56-
err: errBoom,
57-
},
58-
},
59-
}
60-
for n, tc := range cases {
61-
t.Run(n, func(t *testing.T) {
62-
tagger := NewTagger(tc.kube, "tags")
63-
gotErr := tagger.Initialize(context.TODO(), tc.mg)
64-
if diff := cmp.Diff(tc.want.err, gotErr, test.EquateErrors()); diff != "" {
65-
t.Fatalf("generateTypeName(...): -want error, +got error: %s", diff)
66-
}
67-
})
68-
}
30+
type args struct {
31+
mg xpresource.Managed
32+
kube client.Client
33+
}
34+
type want struct {
35+
err error
36+
}
37+
cases := map[string]struct {
38+
args
39+
want
40+
}{
41+
"Successful": {
42+
args: args{
43+
mg: &fake.Managed{},
44+
kube: &test.MockClient{MockUpdate: test.NewMockUpdateFn(nil)},
45+
},
46+
want: want{
47+
err: nil,
48+
},
49+
},
50+
"Failure": {
51+
args: args{
52+
mg: &fake.Managed{},
53+
kube: &test.MockClient{MockUpdate: test.NewMockUpdateFn(errBoom)},
54+
},
55+
want: want{
56+
err: errBoom,
57+
},
58+
},
59+
}
60+
for n, tc := range cases {
61+
t.Run(n, func(t *testing.T) {
62+
tagger := NewTagger(tc.kube, "tags")
63+
gotErr := tagger.Initialize(context.TODO(), tc.mg)
64+
if diff := cmp.Diff(tc.want.err, gotErr, test.EquateErrors()); diff != "" {
65+
t.Fatalf("generateTypeName(...): -want error, +got error: %s", diff)
66+
}
67+
})
68+
}
6969
}
7070

7171
func TestSetExternalTagsWithPaved(t *testing.T) {
72-
type args struct {
73-
externalTags map[string]string
74-
paved *fieldpath.Paved
75-
fieldName string
76-
}
77-
type want struct {
78-
pavedString string
79-
err error
80-
}
81-
cases := map[string]struct {
82-
args
83-
want
84-
}{
85-
"Successful": {
86-
args: args{
87-
externalTags: map[string]string{
88-
xpresource.ExternalResourceTagKeyKind: kind,
89-
xpresource.ExternalResourceTagKeyName: name,
90-
xpresource.ExternalResourceTagKeyProvider: provider,
91-
},
92-
paved: fieldpath.Pave(map[string]any{}),
93-
fieldName: "tags",
94-
},
95-
want: want{
96-
pavedString: fmt.Sprintf(`{"spec":{"forProvider":{"tags":{"%s":"%s","%s":"%s","%s":"%s"}}}}`,
97-
xpresource.ExternalResourceTagKeyKind, kind,
98-
xpresource.ExternalResourceTagKeyName, name,
99-
xpresource.ExternalResourceTagKeyProvider, provider),
100-
},
101-
},
102-
}
103-
for n, tc := range cases {
104-
t.Run(n, func(t *testing.T) {
105-
gotByte, gotErr := setExternalTagsWithPaved(tc.externalTags, tc.paved, tc.fieldName)
106-
if diff := cmp.Diff(tc.want.err, gotErr, test.EquateErrors()); diff != "" {
107-
t.Fatalf("generateTypeName(...): -want error, +got error: %s", diff)
108-
}
109-
if diff := cmp.Diff(tc.want.pavedString, string(gotByte), test.EquateErrors()); diff != "" {
110-
t.Fatalf("generateTypeName(...): -want gotByte, +got gotByte: %s", diff)
111-
}
112-
})
113-
}
72+
type args struct {
73+
externalTags map[string]string
74+
paved *fieldpath.Paved
75+
fieldName string
76+
}
77+
type want struct {
78+
pavedString string
79+
err error
80+
}
81+
cases := map[string]struct {
82+
args
83+
want
84+
}{
85+
"Successful": {
86+
args: args{
87+
externalTags: map[string]string{
88+
xpresource.ExternalResourceTagKeyKind: kind,
89+
xpresource.ExternalResourceTagKeyName: name,
90+
xpresource.ExternalResourceTagKeyProvider: provider,
91+
},
92+
paved: fieldpath.Pave(map[string]any{}),
93+
fieldName: "tags",
94+
},
95+
want: want{
96+
pavedString: fmt.Sprintf(`{"spec":{"forProvider":{"tags":{"%s":"%s","%s":"%s","%s":"%s"}}}}`,
97+
xpresource.ExternalResourceTagKeyKind, kind,
98+
xpresource.ExternalResourceTagKeyName, name,
99+
xpresource.ExternalResourceTagKeyProvider, provider),
100+
},
101+
},
102+
}
103+
for n, tc := range cases {
104+
t.Run(n, func(t *testing.T) {
105+
gotByte, gotErr := setExternalTagsWithPaved(tc.externalTags, tc.paved, tc.fieldName)
106+
if diff := cmp.Diff(tc.want.err, gotErr, test.EquateErrors()); diff != "" {
107+
t.Fatalf("generateTypeName(...): -want error, +got error: %s", diff)
108+
}
109+
if diff := cmp.Diff(tc.want.pavedString, string(gotByte), test.EquateErrors()); diff != "" {
110+
t.Fatalf("generateTypeName(...): -want gotByte, +got gotByte: %s", diff)
111+
}
112+
})
113+
}
114+
}
115+
116+
func TestReferences_AddReference(t *testing.T) {
117+
t.Run("Adding a reference", func(t *testing.T) {
118+
r := &Resource{References: References{}}
119+
err := r.References.AddReference("forwarding_rule.certificate_name", Reference{
120+
TerraformName: "digitalocean_certificate",
121+
})
122+
if err != nil {
123+
t.Fatalf("AddReference() got error: %v", err)
124+
}
125+
if len(r.References) != 1 {
126+
t.Fatalf("AddReference() got error: %v", err)
127+
}
128+
})
129+
t.Run("Adding twice a reference for a given field", func(t *testing.T) {
130+
r := &Resource{References: References{}}
131+
err := r.References.AddReference("forwarding_rule.certificate_name", Reference{
132+
TerraformName: "digitalocean_certificate",
133+
})
134+
if err != nil {
135+
t.Fatalf("AddReference() got error: %v", err)
136+
}
137+
138+
err = r.References.AddReference("forwarding_rule.certificate_name", Reference{
139+
TerraformName: "digitalocean_certificate",
140+
})
141+
if !errors.Is(err, ErrReferenceAlreadyExists) {
142+
t.Fatalf("AddReference() should have returned an error")
143+
}
144+
})
114145
}

0 commit comments

Comments
 (0)