1 package cloudtoedge
2
3 import (
4 "fmt"
5 "net/http"
6 "strings"
7 "testing"
8
9 "cloud.google.com/go/pubsub"
10
11 dsapi "edge-infra.dev/pkg/edge/datasync/apis/v1alpha1"
12 "edge-infra.dev/pkg/edge/datasync/couchdb"
13 "edge-infra.dev/pkg/k8s/testing/kmp"
14 "edge-infra.dev/test/f2"
15 "edge-infra.dev/test/f2/x/ktest"
16
17 "gotest.tools/v3/assert"
18 "gotest.tools/v3/assert/cmp"
19 "gotest.tools/v3/poll"
20
21 corev1 "k8s.io/api/core/v1"
22 "sigs.k8s.io/controller-runtime/pkg/client"
23 )
24
25 func TestDBCreationAndDeletion(t *testing.T) {
26 feature := f2.NewFeature("Datasync DB Creation And Deletion").
27 Test("Create New Database", func(ctx f2.Context, t *testing.T) f2.Context {
28 result := pubSubClient.Topic(pubSubTopic).Publish(ctx, &pubsub.Message{
29 Attributes: map[string]string{
30 "tenant_id": bslInfo.OrganizationID,
31 "db_name": fmt.Sprintf("db-%s", ctx.RunID),
32 "entity_id": ctx.RunID,
33 "entity_type": "json",
34 },
35 Data: tlog,
36 })
37 msgID, err := result.Get(ctx)
38 assert.NilError(t, err, "fail to send C2E message to pub/sub")
39 t.Log("Sent pub/sub message Id:", msgID)
40 return ctx
41 }).
42 Test("Verify DB Exists In The Cloud", func(ctx f2.Context, t *testing.T) f2.Context {
43 k := ktest.FromContextT(ctx, t)
44 secret := corev1.Secret{}
45 key := client.ObjectKey{Namespace: "couchctl", Name: couchdb.StoreReplicationSecretName}
46 err := k.Client.Get(ctx, key, &secret)
47 assert.NilError(t, err, "fail to get couchdb master secret")
48
49 req, err := couchDBRequest(secret, string(secret.Data["uri"]),
50 fmt.Sprintf("db-%s", ctx.RunID), ctx.RunID)
51 assert.NilError(t, err, "fail to create couchdb request")
52
53 var resp *http.Response
54 poll.WaitOn(t, func(_ poll.LogT) poll.Result {
55 resp, err = http.DefaultClient.Do(req)
56 if err == nil && resp.StatusCode == 200 {
57 return poll.Success()
58 }
59 return poll.Continue("fail to confirm existence of docs from couchdb master: %s",
60 errMessage(resp, req, err))
61 }, poll.WithDelay(k.Tick), poll.WithTimeout(k.Timeout*timeoutMultiplier))
62 return ctx
63 }).
64 Test("Verify Replication Is Successful", func(ctx f2.Context, t *testing.T) f2.Context {
65 k := ktest.FromContextT(ctx, t)
66 replications := dsapi.CouchDBReplicationSetList{}
67 err := k.Client.List(ctx, &replications, client.InNamespace(couchNamespace))
68 assert.NilError(t, err, "fail to list couchdb replications")
69 assert.Check(t, cmp.Len(replications.Items, len(nodes.Items)),
70 "number of couchdb replications not equal to number of nodes")
71
72 for _, replication := range replications.Items {
73 repl := replication
74 k.WaitOn(t, k.Check(&repl, kmp.IsReady()))
75 }
76 return ctx
77 }).
78 Test("Verify Message In CouchDB Store", func(ctx f2.Context, t *testing.T) f2.Context {
79 k := ktest.FromContextT(ctx, t)
80 secret := corev1.Secret{}
81 key := client.ObjectKey{Namespace: couchNamespace, Name: couchdb.StoreSecretName}
82
83 err := k.Client.Get(ctx, key, &secret)
84 assert.NilError(t, err, "fail to get couchdb store secret")
85
86 servers := dsapi.CouchDBServerList{}
87 assert.NilError(t, k.Client.List(ctx, &servers), "fail to list couchdb servers")
88
89 for _, server := range servers.Items {
90 pod := strings.Split(server.Spec.URI, ".")[0]
91 portForward := portMapping[pod]
92 addr := portForward.Retrieve(t)
93 req, err := couchDBRequest(secret, fmt.Sprintf("http://%s", addr),
94 fmt.Sprintf("db-%s", ctx.RunID), ctx.RunID)
95 assert.NilError(t, err, "fail to create couchdb request")
96
97 var resp *http.Response
98 poll.WaitOn(t, func(_ poll.LogT) poll.Result {
99 resp, err = http.DefaultClient.Do(req)
100 if err == nil && resp.StatusCode == 200 {
101 return poll.Success()
102 }
103 return poll.Continue("fail to get new db doc from couchdb Store: %s", errMessage(resp, req, err))
104 }, poll.WithDelay(k.Tick), poll.WithTimeout(k.Timeout*timeoutMultiplier))
105 }
106 return ctx
107 }).
108 Test("Delete Created Database", func(ctx f2.Context, t *testing.T) f2.Context {
109 result := pubSubClient.Topic(pubSubTopic).Publish(ctx, &pubsub.Message{
110 Attributes: map[string]string{
111 "tenant_id": bslInfo.OrganizationID,
112 "db_name": fmt.Sprintf("db-%s", ctx.RunID),
113 "entity_id": couchdb.AllDocs,
114 "deleted": "true",
115 "entity_type": "json",
116 },
117 })
118 msgID, err := result.Get(ctx)
119 assert.NilError(t, err, "fail to send delete message to pub/sub")
120 t.Log("Sent pub/sub message Id:", msgID)
121 return ctx
122 }).
123 Test("Verify DB Does Not Exists In The Cloud", func(ctx f2.Context, t *testing.T) f2.Context {
124 k := ktest.FromContextT(ctx, t)
125 secret := corev1.Secret{}
126 key := client.ObjectKey{Namespace: "couchctl", Name: couchdb.StoreReplicationSecretName}
127 err := k.Client.Get(ctx, key, &secret)
128 assert.NilError(t, err, "fail to get couchdb master secret")
129
130 req, err := couchDBRequest(secret, string(secret.Data["uri"]), fmt.Sprintf("db-%s", ctx.RunID), ctx.RunID)
131 assert.NilError(t, err, "fail to create couchdb request")
132
133 var resp *http.Response
134 poll.WaitOn(t, func(_ poll.LogT) poll.Result {
135 resp, err = http.DefaultClient.Do(req)
136 if is404(resp) {
137 return poll.Success()
138 }
139 return poll.Continue("fail to confirm doc deletion from couchdb master: %s", errMessage(resp, req, err))
140 }, poll.WithDelay(k.Tick), poll.WithTimeout(k.Timeout*timeoutMultiplier))
141 return ctx
142 }).
143 Test("Verify Replication Is Successful", func(ctx f2.Context, t *testing.T) f2.Context {
144 k := ktest.FromContextT(ctx, t)
145 replications := dsapi.CouchDBReplicationSetList{}
146 err := k.Client.List(ctx, &replications, client.InNamespace(couchNamespace))
147 assert.NilError(t, err, "fail to list couchdb replications")
148 assert.Check(t, cmp.Len(replications.Items, len(nodes.Items)),
149 "number of couchdb replications not equal to number of nodes")
150
151 for _, replication := range replications.Items {
152 repl := replication
153 k.WaitOn(t, k.Check(&repl, kmp.IsReady()))
154 }
155 return ctx
156 }).
157 Test("Verify DB Does Not Exists In The Store", func(ctx f2.Context, t *testing.T) f2.Context {
158 k := ktest.FromContextT(ctx, t)
159 secret := corev1.Secret{}
160 key := client.ObjectKey{Namespace: couchNamespace, Name: couchdb.StoreSecretName}
161
162 err := k.Client.Get(ctx, key, &secret)
163 assert.NilError(t, err, "fail to get couchdb store secret")
164
165 servers := dsapi.CouchDBServerList{}
166 assert.NilError(t, k.Client.List(ctx, &servers), "fail to list couchdb servers")
167
168 for _, server := range servers.Items {
169 pod := strings.Split(server.Spec.URI, ".")[0]
170 portForward := portMapping[pod]
171 addr := portForward.Retrieve(t)
172 req, err := couchDBRequest(secret, fmt.Sprintf("http://%s", addr),
173 fmt.Sprintf("db-%s", ctx.RunID), ctx.RunID)
174 assert.NilError(t, err, "fail to create couchdb request")
175
176 var resp *http.Response
177 poll.WaitOn(t, func(_ poll.LogT) poll.Result {
178 resp, err = http.DefaultClient.Do(req)
179 if is404(resp) {
180 return poll.Success()
181 }
182 return poll.Continue("fail to confirm doc deletion in couchdb store: %s", errMessage(resp, req, err))
183 }, poll.WithDelay(k.Tick), poll.WithTimeout(k.Timeout*timeoutMultiplier))
184 }
185
186 return ctx
187 }).
188 Feature()
189 f.Test(t, feature)
190 }
191
192 func is404(resp *http.Response) bool {
193 if resp != nil && resp.StatusCode == 404 {
194 return true
195 }
196 return false
197 }
198
View as plain text