@@ -2,9 +2,13 @@ package v3
22
33import (
44 "fmt"
5+ "slices"
56
67 smoothoperatorv1 "github.com/pdok/smooth-operator/api/v1"
78 smoothoperatorvalidation "github.com/pdok/smooth-operator/pkg/validation"
9+ apierrors "k8s.io/apimachinery/pkg/api/errors"
10+ "k8s.io/apimachinery/pkg/runtime/schema"
11+ "k8s.io/apimachinery/pkg/util/validation/field"
812
913 "strings"
1014
@@ -13,79 +17,121 @@ import (
1317)
1418
1519func (atom * Atom ) ValidateCreate (c client.Client ) ([]string , error ) {
16- warnings := []string {}
17- reasons := [] string {}
20+ var warnings []string
21+ var allErrs field. ErrorList
1822
1923 err := smoothoperatorvalidation .ValidateLabelsOnCreate (atom .Labels )
2024 if err != nil {
21- reasons = append (reasons , fmt . Sprintf ( "%v" , err ) )
25+ allErrs = append (allErrs , err )
2226 }
2327
24- ValidateAtom (c , atom , & warnings , & reasons )
28+ ValidateAtom (c , atom , & warnings , & allErrs )
2529
26- if len (reasons ) > 0 {
27- return warnings , fmt . Errorf ( "%s" , strings . Join ( reasons , ". " ))
30+ if len (allErrs ) == 0 {
31+ return warnings , nil
2832 }
2933
30- return warnings , nil
34+ return warnings , apierrors .NewInvalid (
35+ schema.GroupKind {Group : "pdok.nl" , Kind : "Atom" },
36+ atom .Name , allErrs )
3137}
3238
3339func (atom * Atom ) ValidateUpdate (c client.Client , atomOld * Atom ) ([]string , error ) {
34- warnings := []string {}
35- reasons := []string {}
40+ var warnings []string
41+ var allErrs field.ErrorList
42+ smoothoperatorvalidation .ValidateLabelsOnUpdate (atomOld .Labels , atom .Labels , & allErrs )
3643
37- // Check labels did not change
38- err := smoothoperatorvalidation .ValidateLabelsOnUpdate (atomOld .Labels , atom .Labels )
39- if err != nil {
40- reasons = append (reasons , fmt .Sprintf ("%v" , err ))
41- }
42-
43- smoothoperatorvalidation .CheckBaseUrlImmutability (atomOld , atom , & reasons )
44+ smoothoperatorvalidation .CheckBaseUrlImmutability (atomOld , atom , & allErrs )
4445
45- ValidateAtom (c , atom , & warnings , & reasons )
46+ ValidateAtom (c , atom , & warnings , & allErrs )
4647
47- if len (reasons ) > 0 {
48- return warnings , fmt . Errorf ( "%s" , strings . Join ( reasons , ". " ))
48+ if len (allErrs ) == 0 {
49+ return warnings , nil
4950 }
5051
51- return warnings , nil
52+ return warnings , apierrors .NewInvalid (
53+ schema.GroupKind {Group : "pdok.nl" , Kind : "Atom" },
54+ atom .Name , allErrs )
5255}
5356
54- func ValidateAtom (c client.Client , atom * Atom , warnings * []string , reasons * [] string ) {
55- ValidateAtomWithoutClusterChecks (atom , warnings , reasons )
57+ func ValidateAtom (c client.Client , atom * Atom , warnings * []string , allErrs * field. ErrorList ) {
58+ ValidateAtomWithoutClusterChecks (atom , warnings , allErrs )
5659
60+ ownerInfoRef := atom .Spec .Service .OwnerInfoRef
5761 ownerInfo := & smoothoperatorv1.OwnerInfo {}
5862 objectKey := client.ObjectKey {
5963 Namespace : atom .Namespace ,
60- Name : atom . Spec . Service . OwnerInfoRef ,
64+ Name : ownerInfoRef ,
6165 }
6266 ctx := context .Background ()
6367 err := c .Get (ctx , objectKey , ownerInfo )
68+ fieldPath := field .NewPath ("spec" ).Child ("service" ).Child ("ownerInfoRef" )
6469 if err != nil {
65- * reasons = append (* reasons , fmt .Sprintf ("%v" , err ))
70+ * allErrs = append (* allErrs , field .NotFound (fieldPath , ownerInfoRef ))
71+ return
6672 }
6773
6874 if ownerInfo .Spec .Atom == nil {
69- * reasons = append (* reasons , "no atom settings in ownerInfo: "+ ownerInfo .Name )
75+ * allErrs = append (* allErrs , field . Required ( fieldPath , "spec.Atom missing in "+ ownerInfo .Name ) )
7076 }
7177}
7278
73- func ValidateAtomWithoutClusterChecks (atom * Atom , warnings * []string , reasons * []string ) {
79+ func ValidateAtomWithoutClusterChecks (atom * Atom , warnings * []string , allErrs * field.ErrorList ) {
80+ var fieldPath * field.Path
7481 if strings .Contains (atom .GetName (), "atom" ) {
75- * warnings = append (* warnings , smoothoperatorvalidation .FormatValidationWarning ("name should not contain atom" , atom .GroupVersionKind (), atom .GetName ()))
82+ fieldPath = field .NewPath ("metadata" ).Child ("name" )
83+ smoothoperatorvalidation .AddWarning (warnings , * fieldPath , "should not contain atom" , atom .GroupVersionKind (), atom .GetName ())
7684 }
85+ var feedNames []string
86+ for i , datasetFeed := range atom .Spec .Service .DatasetFeeds {
87+ fieldPath = field .NewPath ("spec" ).Child ("service" ).Child ("datasetFeeds" ).Index (i )
7788
78- for _ , datasetFeed := range atom .Spec .Service .DatasetFeeds {
79- for _ , entry := range datasetFeed .Entries {
80- if linkCount := len (entry .DownloadLinks ); linkCount > 1 && entry .Content == nil {
81- * reasons = append (* reasons , "content is required for an Entry with more than 1 DownloadLink" )
89+ if slices .Contains (feedNames , datasetFeed .TechnicalName ) {
90+ * allErrs = append (* allErrs , field .Duplicate (fieldPath .Child ("technicalName" ), datasetFeed .TechnicalName ))
91+ }
92+
93+ feedNames = append (feedNames , datasetFeed .TechnicalName )
94+
95+ if datasetFeed .DatasetMetadataLinks != nil && atom .Spec .Service .ServiceMetadataLinks != nil {
96+ if datasetFeed .DatasetMetadataLinks .MetadataIdentifier == atom .Spec .Service .ServiceMetadataLinks .MetadataIdentifier {
97+ * allErrs = append (* allErrs , field .Invalid (
98+ fieldPath .Child ("datasetMetadataLinks" ).Child ("metadataIdentifier" ),
99+ datasetFeed .DatasetMetadataLinks .MetadataIdentifier ,
100+ fmt .Sprintf ("should not be the same as %s" , field .NewPath ("spec" ).
101+ Child ("service" ).Child ("serviceMetadataLinks" ).Child ("metadataIdentifier" )),
102+ ))
82103 }
83104 }
84- }
85105
86- service := atom .Spec .Service
87- err := smoothoperatorvalidation .ValidateBaseURL (service .BaseURL )
88- if err != nil {
89- * reasons = append (* reasons , fmt .Sprintf ("%v" , err ))
106+ if datasetFeed .DatasetMetadataLinks != nil && datasetFeed .SpatialDatasetIdentifierCode == nil {
107+ * allErrs = append (* allErrs , field .Required (
108+ fieldPath .Child ("spatialDatasetIdentifierCode" ),
109+ fmt .Sprintf ("when %s exists" , fieldPath .Child ("datasetMetadataLinks" ).String ()),
110+ ))
111+ }
112+
113+ if datasetFeed .SpatialDatasetIdentifierCode != nil && datasetFeed .SpatialDatasetIdentifierNamespace == nil {
114+ * allErrs = append (* allErrs , field .Required (
115+ fieldPath .Child ("spatialDatasetIdentifierNamespace" ),
116+ fmt .Sprintf ("when %s exists" , fieldPath .Child ("spatialDatasetIdentifierCode" ).String ()),
117+ ))
118+ }
119+
120+ var entryNames []string
121+ for in , entry := range datasetFeed .Entries {
122+ fieldPath = fieldPath .Child ("entries" ).Index (in )
123+ if linkCount := len (entry .DownloadLinks ); linkCount > 1 && entry .Content == nil {
124+ * allErrs = append (* allErrs , field .Required (
125+ fieldPath .Child ("content" ),
126+ fmt .Sprintf ("when %s has 2 or more elements" , fieldPath .Child ("downloadlinks" ).String ()),
127+ ))
128+ }
129+
130+ if slices .Contains (entryNames , entry .TechnicalName ) {
131+ * allErrs = append (* allErrs , field .Duplicate (fieldPath .Child ("technicalName" ), entry .TechnicalName ))
132+ }
133+
134+ entryNames = append (entryNames , entry .TechnicalName )
135+ }
90136 }
91137}
0 commit comments