Files
grafana/pkg/registry/apps/shorturl/status.go
T
2025-11-10 07:29:33 -03:00

112 lines
3.3 KiB
Go

package shorturl
import (
"context"
"errors"
"fmt"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/registry/rest"
"sigs.k8s.io/structured-merge-diff/v6/fieldpath"
"github.com/grafana/grafana-app-sdk/k8s/apiserver"
"github.com/grafana/grafana-app-sdk/logging"
shorturl "github.com/grafana/grafana/apps/shorturl/pkg/apis/shorturl/v1beta1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/services/shorturls"
)
type statusDualWriter struct {
gv schema.GroupVersion
status *apiserver.StatusREST
legacy *legacyStorage
}
var (
_ rest.Patcher = (*statusDualWriter)(nil)
_ rest.Storage = (*statusDualWriter)(nil)
_ rest.ResetFieldsStrategy = (*statusDualWriter)(nil)
)
// Destroy implements rest.Storage.
func (s *statusDualWriter) Destroy() {}
// New implements rest.Storage.
func (s *statusDualWriter) New() runtime.Object {
return s.legacy.New()
}
// Get implements rest.Patcher.
func (s *statusDualWriter) Get(ctx context.Context, name string, options *v1.GetOptions) (runtime.Object, error) {
return s.legacy.Get(ctx, name, options)
}
// Update implements rest.Patcher.
func (s *statusDualWriter) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *v1.UpdateOptions) (runtime.Object, bool, error) {
requester, err := identity.GetRequester(ctx)
if err != nil {
return nil, false, err
}
shortURL, err := s.legacy.service.GetShortURLByUID(ctx, requester, name)
if err != nil || shortURL == nil {
if errors.Is(err, shorturls.ErrShortURLNotFound) || err == nil {
err = k8serrors.NewNotFound(shorturl.ShortURLKind().GroupVersionResource().GroupResource(), name)
}
return nil, false, err
}
// This ignores the incoming and updates it directly
err = s.legacy.service.UpdateLastSeenAt(ctx, shortURL)
if err != nil {
return nil, false, err
}
getter := func(getter rest.Getter) (*shorturl.ShortURL, error) {
obj, err := getter.Get(ctx, name, &v1.GetOptions{})
if err != nil {
return nil, err
}
val, ok := obj.(*shorturl.ShortURL)
if !ok {
return nil, fmt.Errorf("expected ShortURL but got %T", obj)
}
return val, nil
}
legacy, err := getter(s.legacy)
if err != nil {
return nil, false, err // unable to get legacy object
}
unified, err := getter(s.status)
if err != nil {
logging.FromContext(ctx).Warn("unable to read unified status", "error", err)
return legacy, false, nil
}
// Use the same status from legacy in unified
unified.Status = legacy.Status
_, _, err = s.status.Update(ctx, name, rest.DefaultUpdatedObjectInfo(unified), createValidation, updateValidation, false, options)
if err != nil {
logging.FromContext(ctx).Warn("error updating unified status", "error", err)
}
return legacy, false, err
}
// GetResetFields implements rest.ResetFieldsStrategy
func (s *statusDualWriter) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
fields := map[fieldpath.APIVersion]*fieldpath.Set{
fieldpath.APIVersion(s.gv.String()): fieldpath.NewSet(
fieldpath.MakePathOrDie("spec"),
fieldpath.MakePathOrDie("metadata"),
),
}
return fields
}