Skip to content

Commit 5cbd61b

Browse files
committed
✨ Add 'DatasourceIgnorePatterns' to ignore datasources in the controller
1 parent 95f4703 commit 5cbd61b

File tree

10 files changed

+122
-15
lines changed

10 files changed

+122
-15
lines changed

api/config/v2alpha2/projectconfig_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ type ProjectConfig struct {
5353
// kept disabled unless migrations need to be done.
5454
EnableMigrations bool `json:"enableMigrations"`
5555

56+
// DatasourceIgnorePatterns is a list of regex patterns, that allow datasources in styra
57+
// to be ignored based on their datasource id.
58+
DatasourceIgnorePatterns []string `json:"datasourceIgnorePatterns,omitempty"`
59+
5660
// GitCredentials holds a list of git credential configurations. The
5761
// RepoPrefix of the GitCredential will be matched angainst repository URL in
5862
// order to determine which credential to use. The GitCredential with the

api/config/v2alpha2/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/default/config.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ systemUserRoles:
2727
- SystemOwner
2828
- SystemMetadataManager
2929

30+
#datasourceIgnorePatterns:
31+
# - "^systems/[a-z0-9]+/dontdeleteme/.*"
32+
# - "^libraries/[a-z0-9_]+/deletemenot/.*"
33+
3034
#decisionsExporter:
3135

3236
#opa:

config/samples/styra_v1beta1_system.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ spec:
1717
name: api/authz/decision
1818
reason:
1919
path: result.reasons
20-
20+
datasources:
21+
- path: "test"
2122
# TODO(user): Add fields here

internal/config/config.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package config
1919

2020
import (
2121
"os"
22+
"regexp"
2223

2324
"github.com/bankdata/styra-controller/api/config/v2alpha2"
2425
"github.com/pkg/errors"
@@ -114,3 +115,17 @@ func deserialize(data []byte, scheme *runtime.Scheme) (*v2alpha2.ProjectConfig,
114115

115116
return cfg, nil
116117
}
118+
119+
// MatchesIgnorePattern matches a specified ignore pattern, and excludes matches from being deleted
120+
func MatchesIgnorePattern(ignorePatterns []string, id string) (bool, error) {
121+
for _, patternString := range ignorePatterns {
122+
matches, err := regexp.MatchString(patternString, id)
123+
if err != nil {
124+
return false, errors.Wrapf(err, "could not compile regex pattern: %s", patternString)
125+
}
126+
if matches {
127+
return true, nil
128+
}
129+
}
130+
return false, nil
131+
}

internal/controller/styra/library_controller.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"net/http"
2323
"path"
2424

25+
"github.com/bankdata/styra-controller/internal/config"
2526
ctrlerr "github.com/bankdata/styra-controller/internal/errors"
2627
"github.com/bankdata/styra-controller/internal/predicate"
2728
"github.com/bankdata/styra-controller/internal/sentry"
@@ -254,8 +255,18 @@ func (r *LibraryReconciler) reconcileDatasources(ctx context.Context, log logr.L
254255
continue
255256
}
256257

258+
ignore, err := config.MatchesIgnorePattern(r.Config.DatasourceIgnorePatterns, ds.ID)
259+
if err != nil {
260+
return ctrl.Result{}, ctrlerr.Wrap(err, "Could not check if library datasource should be ignored")
261+
}
262+
263+
if ignore {
264+
log.Info("Datasource is ignored", "id", ds.ID)
265+
continue
266+
}
267+
257268
if _, expected := expectedByID[ds.ID]; !expected {
258-
log.Info("Deleting undeclared datasource")
269+
log.Info("Deleting undeclared datasource", "id", ds.ID)
259270

260271
if _, err := r.Styra.DeleteDatasource(ctx, ds.ID); err != nil {
261272
return ctrl.Result{}, ctrlerr.Wrap(err, "Could not delete library datasource")

internal/controller/styra/system_controller.go

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import (
4949

5050
configv2alpha2 "github.com/bankdata/styra-controller/api/config/v2alpha2"
5151
"github.com/bankdata/styra-controller/api/styra/v1beta1"
52+
"github.com/bankdata/styra-controller/internal/config"
5253
ctrlerr "github.com/bankdata/styra-controller/internal/errors"
5354
"github.com/bankdata/styra-controller/internal/fields"
5455
"github.com/bankdata/styra-controller/internal/finalizer"
@@ -927,9 +928,20 @@ func (r *SystemReconciler) reconcileDatasources(
927928
if ds.Optional {
928929
continue
929930
}
931+
932+
ignore, err := config.MatchesIgnorePattern(r.Config.DatasourceIgnorePatterns, ds.ID)
933+
if err != nil {
934+
return ctrl.Result{}, ctrlerr.Wrap(err, "Could not check if system datasource should be ignored")
935+
}
936+
937+
if ignore {
938+
log.Info("Datasource is ignored", "id", ds.ID)
939+
continue
940+
}
941+
930942
if _, ok := expectedByID[ds.ID]; !ok {
931943
log := log.WithValues("datasourceID", ds.ID)
932-
log.Info("Deleting undeclared datasource")
944+
log.Info("Deleting undeclared datasource", "id", ds.ID)
933945
if _, err := r.Styra.DeleteDatasource(ctx, ds.ID); err != nil {
934946
return ctrl.Result{}, ctrlerr.Wrap(err, "Could not delete datasource").
935947
WithEvent("ErrorDeleteDatasource").
@@ -1279,8 +1291,17 @@ func (r *SystemReconciler) specToSystemConfig(system *v1beta1.System) (*styra.Sy
12791291
}
12801292

12811293
if system.Spec.SourceControl != nil {
1282-
if !isURLValid(system.Spec.SourceControl.Origin.URL) {
1283-
return nil, ctrlerr.New("Invalid URL for source control")
1294+
valid, err := isURLValid(system.Spec.SourceControl.Origin.URL)
1295+
if err != nil {
1296+
return nil, ctrlerr.Wrap(err, "Error while validating URL").
1297+
WithEvent("ErrorUpdateSystem").
1298+
WithSystemCondition(v1beta1.ConditionTypeSystemConfigUpdated)
1299+
}
1300+
1301+
if !valid {
1302+
return nil, ctrlerr.New("Invalid URL for source control").
1303+
WithEvent("ErrorUpdateSystem").
1304+
WithSystemCondition(v1beta1.ConditionTypeSystemConfigUpdated)
12841305
}
12851306

12861307
cfg.SourceControl = &styra.SourceControlConfig{
@@ -1308,23 +1329,27 @@ func (r *SystemReconciler) specToSystemConfig(system *v1beta1.System) (*styra.Sy
13081329
return cfg, nil
13091330
}
13101331

1311-
func isURLValid(u string) bool {
1332+
func isURLValid(u string) (bool, error) {
13121333
//empty url is valid
13131334
if strings.TrimSpace(u) == "" {
1314-
return true
1335+
return true, nil
13151336
}
13161337

13171338
parsedURL, err := url.Parse(u)
13181339
if err != nil {
1319-
return false
1340+
return false, err
13201341
}
13211342
if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" {
1322-
return false
1343+
return false, nil
13231344
}
13241345

13251346
// Regular expression to match valid URL path characters
1326-
re := regexp.MustCompile(`^[a-zA-Z0-9\-._~!$&'()*+,;=:@/]*$`)
1327-
return re.MatchString(parsedURL.Path)
1347+
valid, err := regexp.MatchString(`^[a-zA-Z0-9\-._~!$&'()*+,;=:@/]*$`, parsedURL.Path)
1348+
if err != nil {
1349+
return false, err
1350+
}
1351+
1352+
return valid, nil
13281353
}
13291354

13301355
func (r *SystemReconciler) systemNeedsUpdate(

test/integration/controller/controller_suite_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ var _ = ginkgo.BeforeSuite(func() {
123123
IdentityProvider: "AzureAD Bankdata",
124124
JWTGroupsClaim: "groups",
125125
},
126+
DatasourceIgnorePatterns: []string{"^.*/ignore$"},
126127
ReadOnly: true,
127128
EnableDeltaBundlesDefault: ptr.Bool(false),
128129
},
@@ -161,6 +162,7 @@ var _ = ginkgo.BeforeSuite(func() {
161162
IdentityProvider: "AzureAD Bankdata",
162163
JWTGroupsClaim: "groups",
163164
},
165+
DatasourceIgnorePatterns: []string{"^.*/ignore$"},
164166
GitCredentials: []*configv2alpha2.GitCredential{
165167
{User: "test-user", Password: "test-secret"},
166168
},

test/integration/controller/library_controller_test.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,16 @@ var _ = ginkgo.Describe("LibraryReconciler.Reconcile", ginkgo.Label("integration
125125
styraClientMock.On("GetLibrary", mock.Anything, key.Name).Return(&styra.GetLibraryResponse{
126126
Statuscode: http.StatusOK,
127127
LibraryEntityExpanded: &styra.LibraryEntityExpanded{
128-
DataSources: []styra.LibraryDatasourceConfig{},
128+
DataSources: []styra.LibraryDatasourceConfig{
129+
{
130+
Category: "rest",
131+
ID: path.Join("libraries", key.Name, "ignore"),
132+
},
133+
{
134+
Category: "rest",
135+
ID: path.Join("libraries", key.Name, "delete"),
136+
},
137+
},
129138
Description: "description",
130139
ID: key.Name,
131140
ReadOnly: true,
@@ -141,6 +150,14 @@ var _ = ginkgo.Describe("LibraryReconciler.Reconcile", ginkgo.Label("integration
141150
StatusCode: http.StatusOK,
142151
}, nil).Once()
143152

153+
styraClientMock.On(
154+
"DeleteDatasource",
155+
mock.Anything,
156+
path.Join("libraries", key.Name, "delete")).
157+
Return(&styra.DeleteDatasourceResponse{
158+
StatusCode: http.StatusOK,
159+
}, nil).Once()
160+
144161
webhookMock.On(
145162
"LibraryDatasourceChanged",
146163
mock.Anything,
@@ -267,6 +284,7 @@ var _ = ginkgo.Describe("LibraryReconciler.Reconcile", ginkgo.Label("integration
267284
createInvitation int
268285
createRoleBinding int
269286
listRoleBindings int
287+
deleteDatasource int
270288
)
271289

272290
for _, call := range styraClientMock.Calls {
@@ -287,6 +305,8 @@ var _ = ginkgo.Describe("LibraryReconciler.Reconcile", ginkgo.Label("integration
287305
createRoleBinding++
288306
case "ListRoleBindingsV2":
289307
listRoleBindings++
308+
case "DeleteDatasource":
309+
deleteDatasource++
290310
}
291311
}
292312

@@ -296,7 +316,6 @@ var _ = ginkgo.Describe("LibraryReconciler.Reconcile", ginkgo.Label("integration
296316
datasourceChanged++
297317
}
298318
}
299-
300319
return createUpdateSecret == 2 &&
301320
getLibrary == 2 &&
302321
upsertLibrary == 1 &&
@@ -305,7 +324,8 @@ var _ = ginkgo.Describe("LibraryReconciler.Reconcile", ginkgo.Label("integration
305324
getUser == 2 &&
306325
createInvitation == 1 &&
307326
listRoleBindings == 3 &&
308-
createRoleBinding == 1
327+
createRoleBinding == 1 &&
328+
deleteDatasource == 1
309329
}, timeout, interval).Should(gomega.BeTrue())
310330

311331
resetMock(&webhookMock.Mock)

test/integration/controller/system_controller_test.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,16 @@ discovery:
11341134
Reference: "",
11351135
},
11361136
},
1137+
Datasources: []*styra.DatasourceConfig{
1138+
{
1139+
Category: "rest",
1140+
ID: "systems/system_id/ignore",
1141+
},
1142+
{
1143+
Category: "rest",
1144+
ID: "systems/system_id/delete",
1145+
},
1146+
},
11371147
DecisionMappings: map[string]styra.DecisionMapping{
11381148
"": {},
11391149
"test": {
@@ -1183,6 +1193,12 @@ discovery:
11831193
StatusCode: http.StatusOK,
11841194
}, nil).Once()
11851195

1196+
styraClientMock.On(
1197+
"DeleteDatasource",
1198+
mock.Anything,
1199+
"systems/system_id/delete",
1200+
).Return(&styra.DeleteDatasourceResponse{}, nil).Once()
1201+
11861202
webhookMock.On(
11871203
"SystemDatasourceChanged",
11881204
mock.Anything,
@@ -1200,6 +1216,7 @@ discovery:
12001216
upsertDatasource int
12011217
getOPAConfig int
12021218
datasourceChanged int
1219+
deleteDatasource int
12031220
)
12041221
for _, call := range styraClientMock.Calls {
12051222
switch call.Method {
@@ -1213,6 +1230,8 @@ discovery:
12131230
getOPAConfig++
12141231
case "UpsertDatasource":
12151232
upsertDatasource++
1233+
case "DeleteDatasource":
1234+
deleteDatasource++
12161235
}
12171236
}
12181237

@@ -1228,7 +1247,8 @@ discovery:
12281247
listRolebindingsV2 == 1 &&
12291248
upsertDatasource == 1 &&
12301249
getOPAConfig == 1 &&
1231-
datasourceChanged == 1
1250+
datasourceChanged == 1 &&
1251+
deleteDatasource == 1
12321252
}, timeout, interval).Should(gomega.BeTrue())
12331253

12341254
resetMock(&styraClientMock.Mock)

0 commit comments

Comments
 (0)