Skip to content

Commit 540fbc7

Browse files
committed
test: E2E tests for all kinds
1 parent f6e5c6b commit 540fbc7

12 files changed

Lines changed: 521 additions & 73 deletions

File tree

internal/clients/hana/auditpolicy/auditpolicy_client.go

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,14 @@ func (c Client) Delete(ctx context.Context, parameters *v1alpha1.AuditPolicyPara
155155
return nil
156156
}
157157

158+
func TrimAllUsersFromAction(action string) string {
159+
return strings.ReplaceAll(action, " FOR PRINCIPALS ALL USERS", "")
160+
}
161+
158162
func OptimizeAuditActions(actionStrings []string) []string {
163+
if len(actionStrings) == 0 {
164+
return actionStrings
165+
}
159166
for i := range actionStrings {
160167
actionStrings[i] = strings.ReplaceAll(actionStrings[i], " FOR PRINCIPALS ALL USERS", "")
161168
}
@@ -239,39 +246,6 @@ func parseUsersList(usersPart string) ([]parsedPrincipal, error) {
239246
return parsedUsers, nil
240247
}
241248

242-
func parseIntoActions(action string) ([]parsedAction, error) {
243-
actions := []parsedAction{}
244-
actionNames := action
245-
246-
partialAction := parsedAction{}
247-
if exceptForParts := strings.SplitN(action, " EXCEPT FOR ", 2); len(exceptForParts) == 2 {
248-
actionNames = exceptForParts[0]
249-
afterExceptFor := exceptForParts[1]
250-
partialUsers, err := parseUsersList(afterExceptFor)
251-
if err != nil {
252-
return nil, err
253-
}
254-
partialAction.auditExceptFor = partialUsers
255-
} else if forParts := strings.SplitN(exceptForParts[0], " FOR ", 2); len(forParts) == 2 {
256-
actionNames = forParts[0]
257-
afterFor := forParts[1]
258-
partialUsers, err := parseUsersList(afterFor)
259-
if err != nil {
260-
return nil, err
261-
}
262-
partialAction.auditFor = partialUsers
263-
}
264-
for _, actionName := range strings.Split(actionNames, ",") {
265-
action := parsedAction{
266-
actionNames: []string{strings.ToUpper(strings.TrimSpace(actionName))},
267-
auditFor: partialAction.auditFor,
268-
auditExceptFor: partialAction.auditExceptFor,
269-
}
270-
actions = append(actions, action)
271-
}
272-
return actions, nil
273-
}
274-
275249
func getUniqueString(input []string) string {
276250
sorted := make([]string, len(input))
277251
copy(sorted, input)
@@ -281,23 +255,6 @@ func getUniqueString(input []string) string {
281255
return uniqueString
282256
}
283257

284-
func updatePrincipals(actionNames []string, principals []parsedPrincipal, principalMap map[string][]string, principalSelfMap map[string][]parsedPrincipal) {
285-
users := []string{}
286-
usergroups := []string{}
287-
for _, principal := range principals {
288-
if principal.user != "" {
289-
users = append(users, principal.user)
290-
} else if principal.usergroup != "" {
291-
usergroups = append(usergroups, principal.usergroup)
292-
}
293-
}
294-
uniqueUsersString := getUniqueString(users)
295-
uniqueUsergroupsString := getUniqueString(usergroups)
296-
uniqueString := uniqueUsersString + ";" + uniqueUsergroupsString
297-
principalMap[uniqueString] = append(principalMap[uniqueString], actionNames...)
298-
principalSelfMap[uniqueString] = principals
299-
}
300-
301258
func splitActions(actions []parsedAction) (noUserMap []string, forPrincipalsMap map[string][]string, forPrincipalsSelfMap map[string][]parsedPrincipal, exceptForPrincipalsMap map[string][]string, exceptForPrincipalsSelfMap map[string][]parsedPrincipal) {
302259
noUserMap = []string{}
303260
forPrincipalsMap = make(map[string][]string)
@@ -371,6 +328,56 @@ func stringifyParsedAction(pa parsedAction) string {
371328
return actionStr
372329
}
373330

331+
func parseIntoActions(action string) ([]parsedAction, error) {
332+
actions := []parsedAction{}
333+
actionNames := action
334+
335+
partialAction := parsedAction{}
336+
if exceptForParts := strings.SplitN(action, " EXCEPT FOR ", 2); len(exceptForParts) == 2 {
337+
actionNames = exceptForParts[0]
338+
afterExceptFor := exceptForParts[1]
339+
partialUsers, err := parseUsersList(afterExceptFor)
340+
if err != nil {
341+
return nil, err
342+
}
343+
partialAction.auditExceptFor = partialUsers
344+
} else if forParts := strings.SplitN(exceptForParts[0], " FOR ", 2); len(forParts) == 2 {
345+
actionNames = forParts[0]
346+
afterFor := forParts[1]
347+
partialUsers, err := parseUsersList(afterFor)
348+
if err != nil {
349+
return nil, err
350+
}
351+
partialAction.auditFor = partialUsers
352+
}
353+
for _, actionName := range strings.Split(actionNames, ",") {
354+
action := parsedAction{
355+
actionNames: []string{strings.ToUpper(strings.TrimSpace(actionName))},
356+
auditFor: partialAction.auditFor,
357+
auditExceptFor: partialAction.auditExceptFor,
358+
}
359+
actions = append(actions, action)
360+
}
361+
return actions, nil
362+
}
363+
364+
func updatePrincipals(actionNames []string, principals []parsedPrincipal, principalMap map[string][]string, principalSelfMap map[string][]parsedPrincipal) {
365+
users := []string{}
366+
usergroups := []string{}
367+
for _, principal := range principals {
368+
if principal.user != "" {
369+
users = append(users, principal.user)
370+
} else if principal.usergroup != "" {
371+
usergroups = append(usergroups, principal.usergroup)
372+
}
373+
}
374+
uniqueUsersString := getUniqueString(users)
375+
uniqueUsergroupsString := getUniqueString(usergroups)
376+
uniqueString := uniqueUsersString + ";" + uniqueUsergroupsString
377+
principalMap[uniqueString] = append(principalMap[uniqueString], actionNames...)
378+
principalSelfMap[uniqueString] = principals
379+
}
380+
374381
func prepareCreateSql(parameters *v1alpha1.AuditPolicyParameters) []string {
375382
queryLeft := fmt.Sprintf(`CREATE AUDIT POLICY "%s" AUDITING %s`, utils.EscapeDoubleQuotes(parameters.PolicyName), parameters.AuditStatus)
376383
queryRight := fmt.Sprintf("LEVEL %s TRAIL TYPE TABLE RETENTION %d", parameters.AuditLevel, *parameters.AuditTrailRetention)

internal/clients/hana/privilege/privilege.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/SAP/crossplane-provider-hana/apis/admin/v1alpha1"
1313
"github.com/SAP/crossplane-provider-hana/internal/clients/xsql"
14+
"github.com/SAP/crossplane-provider-hana/internal/utils"
1415
)
1516

1617
const (
@@ -493,7 +494,7 @@ func groupPrivilegesByTypeAndIdentifier(privileges []Privilege) []PrivilegeGroup
493494
}
494495

495496
func GetDefaultPrivilege(defaultSchema string) string {
496-
return fmt.Sprintf(`CREATE ANY ON SCHEMA %s WITH GRANT OPTION`, defaultSchema)
497+
return fmt.Sprintf(`CREATE ANY ON SCHEMA "%s" WITH GRANT OPTION`, utils.EscapeDoubleQuotes(defaultSchema))
497498
}
498499

499500
// FilterManagedPrivileges filters the observed privileges based on the management policy

internal/controller/user/reconciler.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,8 @@ func (c *external) transformParameters(parameters map[string]string) map[string]
568568

569569
func (c *external) buildDesiredParameters(cr *v1alpha1.User) *v1alpha1.UserParameters {
570570
parameters := handleDefaults(cr)
571+
572+
parameters.Parameters = c.transformParameters(parameters.Parameters)
571573
return parameters
572574
}
573575

test/e2e/audit_policy_test.go

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
//go:build e2e
2+
3+
package e2e
4+
5+
import (
6+
"context"
7+
"fmt"
8+
"os"
9+
"testing"
10+
11+
"github.com/SAP/crossplane-provider-hana/apis/admin/v1alpha1"
12+
"github.com/crossplane-contrib/xp-testing/pkg/resources"
13+
14+
"sigs.k8s.io/e2e-framework/klient/decoder"
15+
"sigs.k8s.io/e2e-framework/klient/k8s"
16+
k8sresources "sigs.k8s.io/e2e-framework/klient/k8s/resources"
17+
"sigs.k8s.io/e2e-framework/klient/wait"
18+
"sigs.k8s.io/e2e-framework/klient/wait/conditions"
19+
"sigs.k8s.io/e2e-framework/pkg/envconf"
20+
"sigs.k8s.io/e2e-framework/pkg/features"
21+
)
22+
23+
type AuditPolicyTestConfig struct {
24+
TestConfig *resources.ResourceTestConfig
25+
Resource *k8sresources.Resources
26+
Objects []k8s.Object
27+
}
28+
29+
func TestAuditPolicy(t *testing.T) {
30+
testConfig := resources.NewResourceTestConfig(nil, "AuditPolicy")
31+
32+
c := &AuditPolicyTestConfig{
33+
TestConfig: testConfig,
34+
}
35+
36+
fB := features.New(fmt.Sprintf("%v", testConfig.Kind))
37+
fB.WithLabel("kind", testConfig.Kind)
38+
fB.Setup(c.SetupAuditPolicy)
39+
40+
fB.Assess("create", testConfig.AssessCreate)
41+
42+
fB.Assess("update", c.assessUpdate)
43+
44+
fB.Assess("delete", testConfig.AssessDelete)
45+
46+
fB.Teardown(testConfig.Teardown)
47+
48+
testenv.Test(t, fB.Feature())
49+
}
50+
51+
func (c *AuditPolicyTestConfig) assessUpdate(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
52+
for _, obj := range c.Objects {
53+
if err := c.Resource.Get(ctx, obj.GetName(), obj.GetNamespace(), obj); err != nil {
54+
t.Errorf("failed to get audit policy: %v", err)
55+
return ctx
56+
}
57+
58+
auditPolicy, ok := obj.(*v1alpha1.AuditPolicy)
59+
if !ok {
60+
t.Errorf("failed to cast object to AuditPolicy: %v", obj)
61+
return ctx
62+
}
63+
64+
auditPolicy.Spec.ForProvider.AuditActions = append(auditPolicy.Spec.ForProvider.AuditActions,
65+
"REVOKE ANY",
66+
)
67+
res := cfg.Client().Resources()
68+
69+
err := res.Update(ctx, auditPolicy)
70+
if err != nil {
71+
t.Fatal(err)
72+
}
73+
74+
var fn = func(u k8s.Object) bool {
75+
return u.GetName() == auditPolicy.GetName() && u.GetNamespace() == auditPolicy.GetNamespace()
76+
}
77+
78+
var areAuditActionsUpToDate = func(observed, desired []string) bool {
79+
if len(observed) != len(desired) {
80+
return false
81+
}
82+
for i, action := range observed {
83+
if action != desired[i] {
84+
return false
85+
}
86+
}
87+
return true
88+
}
89+
90+
err = wait.For(
91+
conditions.New(res).ResourceMatch(auditPolicy, fn),
92+
)
93+
if err != nil {
94+
t.Error(err)
95+
}
96+
if err := res.Get(ctx, auditPolicy.GetName(), auditPolicy.GetNamespace(), auditPolicy); err != nil {
97+
t.Errorf("failed to get audit policy after update: %v", err)
98+
} else if !areAuditActionsUpToDate(auditPolicy.Spec.ForProvider.AuditActions, auditPolicy.Spec.ForProvider.AuditActions) {
99+
t.Errorf("audit policy update failed, expected audit actions to be [GRANT ANY, REVOKE ANY], got %v", auditPolicy.Spec.ForProvider.AuditActions)
100+
}
101+
}
102+
103+
return ctx
104+
}
105+
106+
// Setup creates the resource in the cluster
107+
func (c *AuditPolicyTestConfig) SetupAuditPolicy(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
108+
t.Logf("Apply AuditPolicy")
109+
110+
resources.ImportResources(ctx, t, cfg, c.TestConfig.ResourceDirectory)
111+
112+
objects := make([]k8s.Object, 0)
113+
err := decoder.DecodeEachFile(
114+
ctx, os.DirFS(c.TestConfig.ResourceDirectory), "*",
115+
func(ctx context.Context, obj k8s.Object) error {
116+
objects = append(objects, obj)
117+
return nil
118+
},
119+
decoder.MutateNamespace(cfg.Namespace()),
120+
)
121+
if err != nil {
122+
t.Errorf("failed to decode files: %v", err)
123+
return ctx
124+
}
125+
126+
if c.Resource, err = k8sresources.New(cfg.Client().RESTConfig()); err != nil {
127+
t.Errorf("failed to create resource client: %v", err)
128+
return ctx
129+
}
130+
131+
for _, obj := range objects {
132+
if _, ok := obj.(*v1alpha1.AuditPolicy); !ok {
133+
t.Errorf("failed to cast object to AuditPolicy: %v", obj)
134+
return ctx
135+
}
136+
137+
c.Objects = append(c.Objects, obj)
138+
}
139+
140+
return ctx
141+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: admin.hana.sap.crossplane.io/v1alpha1
2+
kind: AuditPolicy
3+
metadata:
4+
name: example-auditpolicy
5+
spec:
6+
forProvider:
7+
policyName: E2E_EXAMPLE_AUDIT_POLICY
8+
auditStatus: UNSUCCESSFUL
9+
auditLevel: INFO
10+
auditActions:
11+
- GRANT ANY
12+
auditTrailRetention: 30
13+
enabled: true
14+
providerConfigRef:
15+
name: example

test/e2e/crs/DbSchema/dbSchema.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ metadata:
44
name: example-schema
55
spec:
66
forProvider:
7-
schemaName: EXAMPLE
7+
schemaName: E2E_EXAMPLE_SCHEMA
88
owner: DBADMIN
99
providerConfigRef:
10-
name: example
10+
name: example

test/e2e/crs/Role/role.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
apiVersion: admin.hana.sap.crossplane.io/v1alpha1
2+
kind: Role
3+
metadata:
4+
name: example-role
5+
spec:
6+
forProvider:
7+
roleName: E2E_EXAMPLE_ROLE
8+
providerConfigRef:
9+
name: example

test/e2e/crs/User/user.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ spec:
1111
key: password
1212
name: e2e-test-user-secret
1313
namespace: default
14-
username: E2ETESTUSER
14+
username: E2E_EXAMPLE_USER
1515
providerConfigRef:
16-
name: example
16+
name: example
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
apiVersion: admin.hana.sap.crossplane.io/v1alpha1
2+
kind: Usergroup
3+
metadata:
4+
name: example-usergroup
5+
spec:
6+
forProvider:
7+
usergroupName: E2E_EXAMPLE_USERGROUP
8+
providerConfigRef:
9+
name: example

0 commit comments

Comments
 (0)