diff --git a/pkg/api/cephr.go b/pkg/api/cephr.go index 3a87953..8f24362 100644 --- a/pkg/api/cephr.go +++ b/pkg/api/cephr.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "slices" - "strconv" reportsv1 "github.com/kyverno/kyverno/api/reports/v1" "github.com/kyverno/reports-server/pkg/storage" @@ -149,7 +148,6 @@ func (c *cephrStore) Create(ctx context.Context, obj runtime.Object, createValid if err != nil { return nil, errors.NewBadRequest(fmt.Sprintf("cannot create cluster ephemeral report: %s", err.Error())) } - klog.Info(r.ResourceVersion) if err := c.broadcaster.Action(watch.Added, r); err != nil { klog.ErrorS(err, "failed to broadcast event") } @@ -331,20 +329,15 @@ func (c *cephrStore) listCephr() (*reportsv1.ClusterEphemeralReportList, error) } func (c *cephrStore) createCephr(report *reportsv1.ClusterEphemeralReport) (*reportsv1.ClusterEphemeralReport, error) { - report.ResourceVersion = fmt.Sprint(1) + report.ResourceVersion = c.store.UseResourceVersion() report.UID = uuid.NewUUID() report.CreationTimestamp = metav1.Now() return report, c.store.ClusterEphemeralReports().Create(context.TODO(), *report) } -func (c *cephrStore) updateCephr(report *reportsv1.ClusterEphemeralReport, oldReport *reportsv1.ClusterEphemeralReport) (*reportsv1.ClusterEphemeralReport, error) { - oldRV, err := strconv.ParseInt(oldReport.ResourceVersion, 10, 64) - if err != nil { - return nil, errorpkg.Wrapf(err, "could not parse resource version") - } - report.ResourceVersion = fmt.Sprint(oldRV + 1) - +func (c *cephrStore) updateCephr(report *reportsv1.ClusterEphemeralReport, _ *reportsv1.ClusterEphemeralReport) (*reportsv1.ClusterEphemeralReport, error) { + report.ResourceVersion = c.store.UseResourceVersion() return report, c.store.ClusterEphemeralReports().Update(context.TODO(), *report) } diff --git a/pkg/api/cpolr.go b/pkg/api/cpolr.go index 8349281..b6b4247 100644 --- a/pkg/api/cpolr.go +++ b/pkg/api/cpolr.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "slices" - "strconv" "github.com/kyverno/reports-server/pkg/storage" "github.com/kyverno/reports-server/pkg/utils" @@ -329,20 +328,15 @@ func (c *cpolrStore) listCpolr() (*v1alpha2.ClusterPolicyReportList, error) { } func (c *cpolrStore) createCpolr(report *v1alpha2.ClusterPolicyReport) (*v1alpha2.ClusterPolicyReport, error) { - report.ResourceVersion = fmt.Sprint(1) + report.ResourceVersion = c.store.UseResourceVersion() report.UID = uuid.NewUUID() report.CreationTimestamp = metav1.Now() return report, c.store.ClusterPolicyReports().Create(context.TODO(), *report) } -func (c *cpolrStore) updateCpolr(report *v1alpha2.ClusterPolicyReport, oldReport *v1alpha2.ClusterPolicyReport) (*v1alpha2.ClusterPolicyReport, error) { - oldRV, err := strconv.ParseInt(oldReport.ResourceVersion, 10, 64) - if err != nil { - return nil, errorpkg.Wrapf(err, "could not parse resource version") - } - report.ResourceVersion = fmt.Sprint(oldRV + 1) - +func (c *cpolrStore) updateCpolr(report *v1alpha2.ClusterPolicyReport, _ *v1alpha2.ClusterPolicyReport) (*v1alpha2.ClusterPolicyReport, error) { + report.ResourceVersion = c.store.UseResourceVersion() return report, c.store.ClusterPolicyReports().Update(context.TODO(), *report) } diff --git a/pkg/api/ephr.go b/pkg/api/ephr.go index ed344fd..d5063d1 100644 --- a/pkg/api/ephr.go +++ b/pkg/api/ephr.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "slices" - "strconv" reportsv1 "github.com/kyverno/kyverno/api/reports/v1" "github.com/kyverno/reports-server/pkg/storage" @@ -350,20 +349,15 @@ func (p *ephrStore) listEphr(namespace string) (*reportsv1.EphemeralReportList, } func (p *ephrStore) createEphr(report *reportsv1.EphemeralReport) (*reportsv1.EphemeralReport, error) { - report.ResourceVersion = fmt.Sprint(1) + report.ResourceVersion = p.store.UseResourceVersion() report.UID = uuid.NewUUID() report.CreationTimestamp = metav1.Now() return report, p.store.EphemeralReports().Create(context.TODO(), *report) } -func (p *ephrStore) updateEphr(report *reportsv1.EphemeralReport, oldReport *reportsv1.EphemeralReport) (*reportsv1.EphemeralReport, error) { - oldRV, err := strconv.ParseInt(oldReport.ResourceVersion, 10, 64) - if err != nil { - return nil, errorpkg.Wrapf(err, "could not parse resource version") - } - report.ResourceVersion = fmt.Sprint(oldRV + 1) - +func (p *ephrStore) updateEphr(report *reportsv1.EphemeralReport, _ *reportsv1.EphemeralReport) (*reportsv1.EphemeralReport, error) { + report.ResourceVersion = p.store.UseResourceVersion() return report, p.store.EphemeralReports().Update(context.TODO(), *report) } diff --git a/pkg/api/polr.go b/pkg/api/polr.go index 78ba95d..c4891fc 100644 --- a/pkg/api/polr.go +++ b/pkg/api/polr.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "slices" - "strconv" "github.com/kyverno/reports-server/pkg/storage" "github.com/kyverno/reports-server/pkg/utils" @@ -160,7 +159,6 @@ func (p *polrStore) Create(ctx context.Context, obj runtime.Object, createValida if err != nil { return nil, errors.NewBadRequest(fmt.Sprintf("cannot create policy report: %s", err.Error())) } - klog.Info(r.ResourceVersion) if err := p.broadcaster.Action(watch.Added, r); err != nil { klog.ErrorS(err, "failed to broadcast event") } @@ -351,20 +349,15 @@ func (p *polrStore) listPolr(namespace string) (*v1alpha2.PolicyReportList, erro } func (p *polrStore) createPolr(report *v1alpha2.PolicyReport) (*v1alpha2.PolicyReport, error) { - report.ResourceVersion = fmt.Sprint(1) + report.ResourceVersion = p.store.UseResourceVersion() report.UID = uuid.NewUUID() report.CreationTimestamp = metav1.Now() return report, p.store.PolicyReports().Create(context.TODO(), *report) } -func (p *polrStore) updatePolr(report *v1alpha2.PolicyReport, oldReport *v1alpha2.PolicyReport) (*v1alpha2.PolicyReport, error) { - oldRV, err := strconv.ParseInt(oldReport.ResourceVersion, 10, 64) - if err != nil { - return nil, errorpkg.Wrapf(err, "could not parse resource version") - } - report.ResourceVersion = fmt.Sprint(oldRV + 1) - +func (p *polrStore) updatePolr(report *v1alpha2.PolicyReport, _ *v1alpha2.PolicyReport) (*v1alpha2.PolicyReport, error) { + report.ResourceVersion = p.store.UseResourceVersion() return report, p.store.PolicyReports().Update(context.TODO(), *report) } diff --git a/pkg/storage/api/interface.go b/pkg/storage/api/interface.go index ce9f833..a3dce2f 100644 --- a/pkg/storage/api/interface.go +++ b/pkg/storage/api/interface.go @@ -46,3 +46,10 @@ type ClusterEphemeralReportsInterface interface { Update(ctx context.Context, cephr reportsv1.ClusterEphemeralReport) error Delete(ctx context.Context, name string) error } + +type Versioning interface { + // SetResourceVersion sets the resource version to the provided value if its higher + SetResourceVersion(string) error + // UseResourceVersion returns the current resource version and increments the value by one + UseResourceVersion() string +} diff --git a/pkg/storage/store.go b/pkg/storage/store.go index fd57bc7..bf7f2d5 100644 --- a/pkg/storage/store.go +++ b/pkg/storage/store.go @@ -8,13 +8,58 @@ import ( ) type Interface interface { + api.Versioning api.Storage } func New(debug bool, config *db.PostgresConfig) (Interface, error) { klog.Infof("setting up storage, debug=%v", debug) if debug { - return inmemory.New(), nil + return &store{ + db: inmemory.New(), + versioning: NewVersioning(), + }, nil } - return db.New(config) + + db, err := db.New(config) + if err != nil { + return nil, err + } + return &store{ + db: db, + versioning: NewVersioning(), + }, nil +} + +type store struct { + db api.Storage + versioning api.Versioning +} + +func (s *store) ClusterEphemeralReports() api.ClusterEphemeralReportsInterface { + return s.db.ClusterEphemeralReports() +} + +func (s *store) ClusterPolicyReports() api.ClusterPolicyReportsInterface { + return s.db.ClusterPolicyReports() +} + +func (s *store) EphemeralReports() api.EphemeralReportsInterface { + return s.db.EphemeralReports() +} + +func (s *store) PolicyReports() api.PolicyReportsInterface { + return s.db.PolicyReports() +} + +func (s *store) Ready() bool { + return s.db.Ready() +} + +func (s *store) SetResourceVersion(val string) error { + return s.versioning.SetResourceVersion(val) +} + +func (s *store) UseResourceVersion() string { + return s.versioning.UseResourceVersion() } diff --git a/pkg/storage/versioning.go b/pkg/storage/versioning.go new file mode 100644 index 0000000..123b0f4 --- /dev/null +++ b/pkg/storage/versioning.go @@ -0,0 +1,40 @@ +package storage + +import ( + "strconv" + "sync" + + "github.com/kyverno/reports-server/pkg/storage/api" +) + +type resourceVersion struct { + sync.Mutex + version uint64 +} + +func NewVersioning() api.Versioning { + return &resourceVersion{ + version: 1, + } +} + +func (r *resourceVersion) SetResourceVersion(val string) error { + r.Lock() + defer r.Unlock() + number, err := strconv.ParseUint(val, 10, 64) + if err != nil { + return err + } + if number > r.version { + r.version = number + } + return nil +} + +func (r *resourceVersion) UseResourceVersion() string { + r.Lock() + defer r.Unlock() + number := strconv.FormatUint(r.version, 10) + r.version += 1 + return number +}