mirror of https://github.com/grafana/grafana
Storage: Show history+trash using the list command (#99009)
Co-authored-by: Stephanie Hingtgen <stephanie.hingtgen@grafana.com>pull/96628/head
parent
67252dfa46
commit
356b32008b
@ -1,37 +0,0 @@ |
||||
package resource |
||||
|
||||
import ( |
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
||||
"k8s.io/apimachinery/pkg/runtime" |
||||
) |
||||
|
||||
// This object is written when an object is deleted
|
||||
type DeletedMarker struct { |
||||
metav1.TypeMeta `json:",inline"` |
||||
metav1.ObjectMeta `json:"metadata,omitempty"` |
||||
} |
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DeletedMarker) DeepCopyInto(out *DeletedMarker) { |
||||
*out = *in |
||||
out.TypeMeta = in.TypeMeta |
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) |
||||
} |
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeletedMarker.
|
||||
func (in *DeletedMarker) DeepCopy() *DeletedMarker { |
||||
if in == nil { |
||||
return nil |
||||
} |
||||
out := new(DeletedMarker) |
||||
in.DeepCopyInto(out) |
||||
return out |
||||
} |
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *DeletedMarker) DeepCopyObject() runtime.Object { |
||||
if c := in.DeepCopy(); c != nil { |
||||
return c |
||||
} |
||||
return nil |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,9 @@ |
||||
SELECT |
||||
{{ .Ident "guid" }}, |
||||
{{ .Ident "value" }}, |
||||
{{ .Ident "group" }}, |
||||
{{ .Ident "resource" }}, |
||||
{{ .Ident "previous_resource_version" }} |
||||
FROM {{ .Ident "resource_history" }} |
||||
WHERE {{ .Ident "action" }} = 3 |
||||
AND {{ .Ident "value" }} LIKE {{ .Arg .MarkerQuery }}; |
||||
@ -0,0 +1,5 @@ |
||||
SELECT {{ .Ident "value" }} |
||||
FROM {{ .Ident "resource_history" }} |
||||
WHERE {{ .Ident "group" }} = {{ .Arg .Group }} |
||||
AND {{ .Ident "resource" }} = {{ .Arg .Resource }} |
||||
AND {{ .Ident "resource_version" }} = {{ .Arg .RV }}; |
||||
@ -0,0 +1,4 @@ |
||||
UPDATE {{ .Ident "resource_history" }} |
||||
SET {{ .Ident "value" }} = {{ .Arg .Value }} |
||||
WHERE {{ .Ident "guid" }} = {{ .Arg .GUID }} |
||||
; |
||||
@ -0,0 +1,4 @@ |
||||
DELETE FROM {{ .Ident "resource_history" }} |
||||
WHERE 1 = 1 |
||||
AND {{ .Ident "guid" }} = {{ .Arg .GUID }} |
||||
|
||||
@ -0,0 +1,21 @@ |
||||
SELECT |
||||
{{ .Ident "resource_version" }}, |
||||
{{ .Ident "namespace" }}, |
||||
{{ .Ident "name" }}, |
||||
{{ .Ident "folder" }}, |
||||
{{ .Ident "value" }} |
||||
FROM {{ .Ident "resource_history" }} |
||||
WHERE 1 = 1 |
||||
AND {{ .Ident "namespace" }} = {{ .Arg .Key.Namespace }} |
||||
AND {{ .Ident "group" }} = {{ .Arg .Key.Group }} |
||||
AND {{ .Ident "resource" }} = {{ .Arg .Key.Resource }} |
||||
{{ if .Key.Name }} |
||||
AND {{ .Ident "name" }} = {{ .Arg .Key.Name }} |
||||
{{ end }} |
||||
{{ if .Trash }} |
||||
AND {{ .Ident "action" }} = 3 |
||||
{{ end }} |
||||
{{ if (gt .StartRV 0) }} |
||||
AND {{ .Ident "resource_version" }} > {{ .Arg .StartRV }} |
||||
{{ end }} |
||||
ORDER BY resource_version DESC |
||||
@ -0,0 +1,133 @@ |
||||
package sql |
||||
|
||||
import ( |
||||
"context" |
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" |
||||
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils" |
||||
"github.com/grafana/grafana/pkg/storage/unified/sql/db" |
||||
"github.com/grafana/grafana/pkg/storage/unified/sql/dbutil" |
||||
"github.com/grafana/grafana/pkg/storage/unified/sql/sqltemplate" |
||||
) |
||||
|
||||
// This runs functions before the server is returned as healthy
|
||||
func (b *backend) runStartupDataMigrations(ctx context.Context) error { |
||||
if b.skipDataMigration { |
||||
return nil |
||||
} |
||||
|
||||
type migrateRow struct { |
||||
GUID string |
||||
Marker *unstructured.Unstructured |
||||
Group string |
||||
Resource string |
||||
PreviousRV int64 |
||||
} |
||||
|
||||
// Migrate DeletedMarker to regular resource
|
||||
err := b.db.WithTx(ctx, ReadCommitted, func(ctx context.Context, tx db.Tx) error { |
||||
req := &sqlMigrationQueryRequest{ |
||||
SQLTemplate: sqltemplate.New(b.dialect), |
||||
MarkerQuery: `{"kind":"DeletedMarker"%`, |
||||
} |
||||
|
||||
// 1. Find rows with the existing deletion marker
|
||||
rows, err := dbutil.QueryRows(ctx, tx, sqlMigratorGetDeletionMarkers, req) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
migrateRows := make([]migrateRow, 0) |
||||
for rows.Next() { |
||||
item := migrateRow{Marker: &unstructured.Unstructured{}} |
||||
err = rows.Scan(&item.GUID, &req.Value, &item.Group, &item.Resource, &item.PreviousRV) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
err = item.Marker.UnmarshalJSON([]byte(req.Value)) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
migrateRows = append(migrateRows, item) |
||||
} |
||||
err = rows.Close() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
for _, item := range migrateRows { |
||||
// 2. Load the previous value referenced by that marker
|
||||
req := &sqlMigrationQueryRequest{ |
||||
SQLTemplate: sqltemplate.New(b.dialect), |
||||
Group: item.Group, |
||||
Resource: item.Resource, |
||||
RV: item.PreviousRV, |
||||
GUID: item.GUID, |
||||
} |
||||
rows, err = dbutil.QueryRows(ctx, tx, sqlMigratorGetValueFromRV, req) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
if rows.Next() { |
||||
err = rows.Scan(&req.Value) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
} |
||||
err = rows.Close() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
req.Reset() |
||||
|
||||
if len(req.Value) > 0 { |
||||
previous := &unstructured.Unstructured{} |
||||
err = previous.UnmarshalJSON([]byte(req.Value)) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
// 3. Prepare a new payload
|
||||
metaMarker, _ := utils.MetaAccessor(item.Marker) |
||||
metaPrev, _ := utils.MetaAccessor(previous) |
||||
metaPrev.SetDeletionTimestamp(metaMarker.GetDeletionTimestamp()) |
||||
metaPrev.SetFinalizers(nil) |
||||
metaPrev.SetManagedFields(nil) |
||||
metaPrev.SetGeneration(utils.DeletedGeneration) |
||||
metaPrev.SetAnnotation(utils.AnnoKeyKubectlLastAppliedConfig, "") // clears it
|
||||
ts, _ := metaMarker.GetUpdatedTimestamp() |
||||
if ts != nil { |
||||
metaPrev.SetUpdatedTimestamp(ts) |
||||
} |
||||
buff, err := previous.MarshalJSON() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
req.Value = string(buff) |
||||
|
||||
// 4. Update the SQL row with this new value
|
||||
b.log.Info("Migrating DeletedMarker", "guid", req.GUID, "group", req.Group, "resource", req.Resource) |
||||
_, err = dbutil.Exec(ctx, tx, sqlMigratorUpdateValueWithGUID, req) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
} else { |
||||
// 5. If the previous version is missing, we delete it -- there is nothing to help us restore anyway
|
||||
b.log.Warn("Removing orphan deletion marker", "guid", req.GUID, "group", req.Group, "resource", req.Resource) |
||||
_, err = dbutil.Exec(ctx, tx, sqlResourceHistoryDelete, &sqlResourceHistoryDeleteRequest{ |
||||
SQLTemplate: sqltemplate.New(b.dialect), |
||||
GUID: req.GUID, |
||||
}) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
} |
||||
} |
||||
|
||||
return nil |
||||
}) |
||||
|
||||
return err |
||||
} |
||||
@ -0,0 +1,9 @@ |
||||
SELECT |
||||
`guid`, |
||||
`value`, |
||||
`group`, |
||||
`resource`, |
||||
`previous_resource_version` |
||||
FROM `resource_history` |
||||
WHERE `action` = 3 |
||||
AND `value` LIKE '{"kind":"DeletedMarker"%'; |
||||
@ -0,0 +1,5 @@ |
||||
SELECT `value` |
||||
FROM `resource_history` |
||||
WHERE `group` = 'ggg' |
||||
AND `resource` = 'rrr' |
||||
AND `resource_version` = 1234; |
||||
@ -0,0 +1,4 @@ |
||||
UPDATE `resource_history` |
||||
SET `value` = '{new value}' |
||||
WHERE `guid` = 'ggggg' |
||||
; |
||||
@ -0,0 +1,3 @@ |
||||
DELETE FROM `resource_history` |
||||
WHERE 1 = 1 |
||||
AND `guid` = 'xxxx' |
||||
@ -0,0 +1,13 @@ |
||||
SELECT |
||||
`resource_version`, |
||||
`namespace`, |
||||
`name`, |
||||
`folder`, |
||||
`value` |
||||
FROM `resource_history` |
||||
WHERE 1 = 1 |
||||
AND `namespace` = 'nn' |
||||
AND `group` = 'gg' |
||||
AND `resource` = 'rr' |
||||
AND `name` = 'name' |
||||
ORDER BY resource_version DESC |
||||
@ -0,0 +1,14 @@ |
||||
SELECT |
||||
`resource_version`, |
||||
`namespace`, |
||||
`name`, |
||||
`folder`, |
||||
`value` |
||||
FROM `resource_history` |
||||
WHERE 1 = 1 |
||||
AND `namespace` = 'nn' |
||||
AND `group` = 'gg' |
||||
AND `resource` = 'rr' |
||||
AND `action` = 3 |
||||
AND `resource_version` > 123456 |
||||
ORDER BY resource_version DESC |
||||
@ -0,0 +1,13 @@ |
||||
SELECT |
||||
`resource_version`, |
||||
`namespace`, |
||||
`name`, |
||||
`folder`, |
||||
`value` |
||||
FROM `resource_history` |
||||
WHERE 1 = 1 |
||||
AND `namespace` = 'nn' |
||||
AND `group` = 'gg' |
||||
AND `resource` = 'rr' |
||||
AND `action` = 3 |
||||
ORDER BY resource_version DESC |
||||
@ -0,0 +1,9 @@ |
||||
SELECT |
||||
"guid", |
||||
"value", |
||||
"group", |
||||
"resource", |
||||
"previous_resource_version" |
||||
FROM "resource_history" |
||||
WHERE "action" = 3 |
||||
AND "value" LIKE '{"kind":"DeletedMarker"%'; |
||||
@ -0,0 +1,5 @@ |
||||
SELECT "value" |
||||
FROM "resource_history" |
||||
WHERE "group" = 'ggg' |
||||
AND "resource" = 'rrr' |
||||
AND "resource_version" = 1234; |
||||
@ -0,0 +1,4 @@ |
||||
UPDATE "resource_history" |
||||
SET "value" = '{new value}' |
||||
WHERE "guid" = 'ggggg' |
||||
; |
||||
@ -0,0 +1,3 @@ |
||||
DELETE FROM "resource_history" |
||||
WHERE 1 = 1 |
||||
AND "guid" = 'xxxx' |
||||
@ -0,0 +1,13 @@ |
||||
SELECT |
||||
"resource_version", |
||||
"namespace", |
||||
"name", |
||||
"folder", |
||||
"value" |
||||
FROM "resource_history" |
||||
WHERE 1 = 1 |
||||
AND "namespace" = 'nn' |
||||
AND "group" = 'gg' |
||||
AND "resource" = 'rr' |
||||
AND "name" = 'name' |
||||
ORDER BY resource_version DESC |
||||
@ -0,0 +1,14 @@ |
||||
SELECT |
||||
"resource_version", |
||||
"namespace", |
||||
"name", |
||||
"folder", |
||||
"value" |
||||
FROM "resource_history" |
||||
WHERE 1 = 1 |
||||
AND "namespace" = 'nn' |
||||
AND "group" = 'gg' |
||||
AND "resource" = 'rr' |
||||
AND "action" = 3 |
||||
AND "resource_version" > 123456 |
||||
ORDER BY resource_version DESC |
||||
@ -0,0 +1,13 @@ |
||||
SELECT |
||||
"resource_version", |
||||
"namespace", |
||||
"name", |
||||
"folder", |
||||
"value" |
||||
FROM "resource_history" |
||||
WHERE 1 = 1 |
||||
AND "namespace" = 'nn' |
||||
AND "group" = 'gg' |
||||
AND "resource" = 'rr' |
||||
AND "action" = 3 |
||||
ORDER BY resource_version DESC |
||||
@ -0,0 +1,9 @@ |
||||
SELECT |
||||
"guid", |
||||
"value", |
||||
"group", |
||||
"resource", |
||||
"previous_resource_version" |
||||
FROM "resource_history" |
||||
WHERE "action" = 3 |
||||
AND "value" LIKE '{"kind":"DeletedMarker"%'; |
||||
@ -0,0 +1,5 @@ |
||||
SELECT "value" |
||||
FROM "resource_history" |
||||
WHERE "group" = 'ggg' |
||||
AND "resource" = 'rrr' |
||||
AND "resource_version" = 1234; |
||||
@ -0,0 +1,4 @@ |
||||
UPDATE "resource_history" |
||||
SET "value" = '{new value}' |
||||
WHERE "guid" = 'ggggg' |
||||
; |
||||
@ -0,0 +1,3 @@ |
||||
DELETE FROM "resource_history" |
||||
WHERE 1 = 1 |
||||
AND "guid" = 'xxxx' |
||||
@ -0,0 +1,13 @@ |
||||
SELECT |
||||
"resource_version", |
||||
"namespace", |
||||
"name", |
||||
"folder", |
||||
"value" |
||||
FROM "resource_history" |
||||
WHERE 1 = 1 |
||||
AND "namespace" = 'nn' |
||||
AND "group" = 'gg' |
||||
AND "resource" = 'rr' |
||||
AND "name" = 'name' |
||||
ORDER BY resource_version DESC |
||||
@ -0,0 +1,14 @@ |
||||
SELECT |
||||
"resource_version", |
||||
"namespace", |
||||
"name", |
||||
"folder", |
||||
"value" |
||||
FROM "resource_history" |
||||
WHERE 1 = 1 |
||||
AND "namespace" = 'nn' |
||||
AND "group" = 'gg' |
||||
AND "resource" = 'rr' |
||||
AND "action" = 3 |
||||
AND "resource_version" > 123456 |
||||
ORDER BY resource_version DESC |
||||
@ -0,0 +1,13 @@ |
||||
SELECT |
||||
"resource_version", |
||||
"namespace", |
||||
"name", |
||||
"folder", |
||||
"value" |
||||
FROM "resource_history" |
||||
WHERE 1 = 1 |
||||
AND "namespace" = 'nn' |
||||
AND "group" = 'gg' |
||||
AND "resource" = 'rr' |
||||
AND "action" = 3 |
||||
ORDER BY resource_version DESC |
||||
Loading…
Reference in new issue