Skip to content

Commit f553203

Browse files
committed
test: add tests
1 parent cdfeeba commit f553203

File tree

4 files changed

+205
-159
lines changed

4 files changed

+205
-159
lines changed

internal/controller/account_controller_test.go

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -18,67 +18,74 @@ package controller
1818

1919
import (
2020
"context"
21+
"os"
22+
"testing"
2123

22-
. "github.com/onsi/ginkgo/v2"
24+
"github.com/fluxcd/pkg/runtime/conditions"
2325
. "github.com/onsi/gomega"
24-
"k8s.io/apimachinery/pkg/api/errors"
25-
"k8s.io/apimachinery/pkg/types"
26-
"sigs.k8s.io/controller-runtime/pkg/reconcile"
26+
v1 "k8s.io/api/core/v1"
27+
28+
"k8s.io/apimachinery/pkg/runtime"
29+
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
30+
"sigs.k8s.io/controller-runtime/pkg/client/fake"
2731

2832
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2933

34+
"github.com/cloudflare/cloudflare-go"
3035
cloudflareoperatoriov1 "github.com/containeroo/cloudflare-operator/api/v1"
3136
)
3237

33-
var _ = Describe("Account Controller", func() {
34-
Context("When reconciling a resource", func() {
35-
const resourceName = "test-resource"
38+
func NewTestScheme() *runtime.Scheme {
39+
s := runtime.NewScheme()
40+
utilruntime.Must(v1.AddToScheme(s))
41+
utilruntime.Must(cloudflareoperatoriov1.AddToScheme(s))
42+
return s
43+
}
44+
45+
var cf cloudflare.API
3646

37-
ctx := context.Background()
47+
func TestAccountReconciler_reconcileAccount(t *testing.T) {
48+
t.Run("reconciles account", func(t *testing.T) {
49+
g := NewWithT(t)
3850

39-
typeNamespacedName := types.NamespacedName{
40-
Name: resourceName,
41-
Namespace: "default", // TODO(user):Modify as needed
51+
secret := &v1.Secret{
52+
ObjectMeta: metav1.ObjectMeta{
53+
Name: "secret",
54+
Namespace: "default",
55+
},
56+
Data: map[string][]byte{
57+
"apiToken": []byte(os.Getenv("CF_API_TOKEN")),
58+
},
4259
}
43-
account := &cloudflareoperatoriov1.Account{}
44-
45-
BeforeEach(func() {
46-
By("creating the custom resource for the Kind Account")
47-
err := k8sClient.Get(ctx, typeNamespacedName, account)
48-
if err != nil && errors.IsNotFound(err) {
49-
resource := &cloudflareoperatoriov1.Account{
50-
ObjectMeta: metav1.ObjectMeta{
51-
Name: resourceName,
60+
61+
account := &cloudflareoperatoriov1.Account{
62+
ObjectMeta: metav1.ObjectMeta{
63+
Name: "account",
64+
},
65+
Spec: cloudflareoperatoriov1.AccountSpec{
66+
ApiToken: cloudflareoperatoriov1.AccountSpecApiToken{
67+
SecretRef: v1.SecretReference{
68+
Name: "secret",
5269
Namespace: "default",
5370
},
54-
// TODO(user): Specify other spec details if needed.
55-
}
56-
Expect(k8sClient.Create(ctx, resource)).To(Succeed())
57-
}
58-
})
59-
60-
AfterEach(func() {
61-
// TODO(user): Cleanup logic after each test, like removing the resource instance.
62-
resource := &cloudflareoperatoriov1.Account{}
63-
err := k8sClient.Get(ctx, typeNamespacedName, resource)
64-
Expect(err).NotTo(HaveOccurred())
65-
66-
By("Cleanup the specific resource instance Account")
67-
Expect(k8sClient.Delete(ctx, resource)).To(Succeed())
68-
})
69-
It("should successfully reconcile the resource", func() {
70-
By("Reconciling the created resource")
71-
controllerReconciler := &AccountReconciler{
72-
Client: k8sClient,
73-
Scheme: k8sClient.Scheme(),
74-
}
75-
76-
_, err := controllerReconciler.Reconcile(ctx, reconcile.Request{
77-
NamespacedName: typeNamespacedName,
78-
})
79-
Expect(err).NotTo(HaveOccurred())
80-
// TODO(user): Add more specific assertions depending on your controller's reconciliation logic.
81-
// Example: If you expect a certain status condition after reconciliation, verify it here.
82-
})
71+
},
72+
},
73+
}
74+
75+
r := &AccountReconciler{
76+
Client: fake.NewClientBuilder().
77+
WithScheme(NewTestScheme()).
78+
WithObjects(secret, account).
79+
Build(),
80+
Cf: &cf,
81+
}
82+
83+
_ = r.reconcileAccount(context.TODO(), account)
84+
85+
g.Expect(account.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{
86+
*conditions.TrueCondition(cloudflareoperatoriov1.ConditionTypeReady, cloudflareoperatoriov1.ConditionReasonReady, "Account is ready"),
87+
}))
88+
89+
g.Expect(cf.APIToken).To(Equal(string(secret.Data["apiToken"])))
8390
})
84-
})
91+
}

internal/controller/ip_controller_test.go

Lines changed: 79 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -18,67 +18,91 @@ package controller
1818

1919
import (
2020
"context"
21+
"net/http"
22+
"testing"
2123

22-
. "github.com/onsi/ginkgo/v2"
24+
"github.com/fluxcd/pkg/runtime/conditions"
2325
. "github.com/onsi/gomega"
24-
"k8s.io/apimachinery/pkg/api/errors"
25-
"k8s.io/apimachinery/pkg/types"
26-
"sigs.k8s.io/controller-runtime/pkg/reconcile"
26+
27+
"sigs.k8s.io/controller-runtime/pkg/client/fake"
2728

2829
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2930

3031
cloudflareoperatoriov1 "github.com/containeroo/cloudflare-operator/api/v1"
3132
)
3233

33-
var _ = Describe("IP Controller", func() {
34-
Context("When reconciling a resource", func() {
35-
const resourceName = "test-resource"
36-
37-
ctx := context.Background()
38-
39-
typeNamespacedName := types.NamespacedName{
40-
Name: resourceName,
41-
Namespace: "default", // TODO(user):Modify as needed
42-
}
43-
ip := &cloudflareoperatoriov1.IP{}
44-
45-
BeforeEach(func() {
46-
By("creating the custom resource for the Kind IP")
47-
err := k8sClient.Get(ctx, typeNamespacedName, ip)
48-
if err != nil && errors.IsNotFound(err) {
49-
resource := &cloudflareoperatoriov1.IP{
50-
ObjectMeta: metav1.ObjectMeta{
51-
Name: resourceName,
52-
Namespace: "default",
53-
},
54-
// TODO(user): Specify other spec details if needed.
55-
}
56-
Expect(k8sClient.Create(ctx, resource)).To(Succeed())
57-
}
58-
})
59-
60-
AfterEach(func() {
61-
// TODO(user): Cleanup logic after each test, like removing the resource instance.
62-
resource := &cloudflareoperatoriov1.IP{}
63-
err := k8sClient.Get(ctx, typeNamespacedName, resource)
64-
Expect(err).NotTo(HaveOccurred())
65-
66-
By("Cleanup the specific resource instance IP")
67-
Expect(k8sClient.Delete(ctx, resource)).To(Succeed())
68-
})
69-
It("should successfully reconcile the resource", func() {
70-
By("Reconciling the created resource")
71-
controllerReconciler := &IPReconciler{
72-
Client: k8sClient,
73-
Scheme: k8sClient.Scheme(),
74-
}
75-
76-
_, err := controllerReconciler.Reconcile(ctx, reconcile.Request{
77-
NamespacedName: typeNamespacedName,
78-
})
79-
Expect(err).NotTo(HaveOccurred())
80-
// TODO(user): Add more specific assertions depending on your controller's reconciliation logic.
81-
// Example: If you expect a certain status condition after reconciliation, verify it here.
82-
})
34+
func StartIPSource() {
35+
http.HandleFunc("/plain", func(w http.ResponseWriter, r *http.Request) {
36+
_, _ = w.Write([]byte("1.1.1.1"))
37+
})
38+
http.HandleFunc("/json", func(w http.ResponseWriter, r *http.Request) {
39+
_, _ = w.Write([]byte(`{"ip":"1.1.1.1"}`))
40+
})
41+
_ = http.ListenAndServe(":8080", nil)
42+
}
43+
44+
func TestIPReconciler_reconcileIP(t *testing.T) {
45+
g := NewWithT(t)
46+
47+
ip := &cloudflareoperatoriov1.IP{
48+
ObjectMeta: metav1.ObjectMeta{
49+
Name: "ip",
50+
},
51+
Spec: cloudflareoperatoriov1.IPSpec{
52+
Type: "dynamic",
53+
},
54+
}
55+
56+
r := &IPReconciler{
57+
Client: fake.NewClientBuilder().
58+
WithScheme(NewTestScheme()).
59+
WithObjects().
60+
Build(),
61+
}
62+
63+
go StartIPSource()
64+
65+
t.Run("reconciles dynamic ip plain text", func(t *testing.T) {
66+
ip.Spec.IPSources = []cloudflareoperatoriov1.IPSpecIPSources{{
67+
URL: "http://localhost:8080/plain",
68+
}}
69+
70+
_ = r.reconcileIP(context.TODO(), ip)
71+
72+
g.Expect(ip.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{
73+
*conditions.TrueCondition(cloudflareoperatoriov1.ConditionTypeReady, cloudflareoperatoriov1.ConditionReasonReady, "IP is ready"),
74+
}))
75+
76+
g.Expect(ip.Spec.Address).To(Equal("1.1.1.1"))
77+
})
78+
79+
t.Run("reconciles dynamic ip jq filter", func(t *testing.T) {
80+
ip.Spec.IPSources = []cloudflareoperatoriov1.IPSpecIPSources{{
81+
URL: "http://localhost:8080/json",
82+
ResponseJQFilter: ".ip",
83+
}}
84+
85+
_ = r.reconcileIP(context.TODO(), ip)
86+
87+
g.Expect(ip.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{
88+
*conditions.TrueCondition(cloudflareoperatoriov1.ConditionTypeReady, cloudflareoperatoriov1.ConditionReasonReady, "IP is ready"),
89+
}))
90+
91+
g.Expect(ip.Spec.Address).To(Equal("1.1.1.1"))
92+
})
93+
94+
t.Run("reconciles dynamic ip regex", func(t *testing.T) {
95+
ip.Spec.IPSources = []cloudflareoperatoriov1.IPSpecIPSources{{
96+
URL: "http://localhost:8080/json",
97+
PostProcessingRegex: "([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)",
98+
}}
99+
100+
_ = r.reconcileIP(context.TODO(), ip)
101+
102+
g.Expect(ip.Status.Conditions).To(conditions.MatchConditions([]metav1.Condition{
103+
*conditions.TrueCondition(cloudflareoperatoriov1.ConditionTypeReady, cloudflareoperatoriov1.ConditionReasonReady, "IP is ready"),
104+
}))
105+
106+
g.Expect(ip.Spec.Address).To(Equal("1.1.1.1"))
83107
})
84-
})
108+
}

internal/controller/suite_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import (
3535
networkingv1 "k8s.io/api/networking/v1"
3636

3737
cloudflareoperatoriov1 "github.com/containeroo/cloudflare-operator/api/v1"
38-
//+kubebuilder:scaffold:imports
38+
// +kubebuilder:scaffold:imports
3939
)
4040

4141
// These tests use Ginkgo (BDD-style Go testing framework). Refer to
@@ -82,7 +82,7 @@ var _ = BeforeSuite(func() {
8282
err = networkingv1.AddToScheme(scheme.Scheme)
8383
Expect(err).NotTo(HaveOccurred())
8484

85-
//+kubebuilder:scaffold:scheme
85+
// +kubebuilder:scaffold:scheme
8686

8787
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
8888
Expect(err).NotTo(HaveOccurred())

0 commit comments

Comments
 (0)