Skip to content

Commit

Permalink
Migrate old db_object_import_rule preset to new preset
Browse files Browse the repository at this point in the history
  • Loading branch information
greedy52 committed Oct 17, 2024
1 parent 22edf09 commit 06f0b04
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 2 deletions.
19 changes: 19 additions & 0 deletions lib/auth/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -1131,6 +1131,25 @@ func createPresetDatabaseObjectImportRule(ctx context.Context, rules services.Da
return trace.Wrap(err, "failed listing available database object import rules")
}
if len(importRules) > 0 {
// If the single rule is the old preset, we assume the user hasn't used
// DB DAC feature yet since the old preset alone is usually not enough
// to make things work. Replace it with the new preset.
//
// Creating and updating the database object import rule is handled on
// a best-effort basis, so it’s not included in backend migrations.
//
// TODO(greedy52) DELETE in 18.0
if len(importRules) == 1 && databaseobjectimportrule.IsOldImportAllObjectsRulePreset(importRules[0]) {
rule := databaseobjectimportrule.NewPresetImportAllObjectsRule()
if rule == nil {
return nil
}

_, err = rules.UpsertDatabaseObjectImportRule(ctx, rule)
if err != nil {
return trace.Wrap(err, "failed to update the default database object import rule")
}
}
return nil
}

Expand Down
108 changes: 108 additions & 0 deletions lib/auth/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ import (

"github.com/gravitational/teleport"
"github.com/gravitational/teleport/api/constants"
dbobjectimportrulev1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobjectimportrule/v1"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/types/label"
apisshutils "github.com/gravitational/teleport/api/utils/sshutils"
"github.com/gravitational/teleport/entitlements"
"github.com/gravitational/teleport/lib"
Expand All @@ -58,6 +60,7 @@ import (
"github.com/gravitational/teleport/lib/observability/tracing"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/services/suite"
"github.com/gravitational/teleport/lib/srv/db/common/databaseobjectimportrule"
"github.com/gravitational/teleport/lib/sshutils"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/teleport/lib/utils/proxy"
Expand Down Expand Up @@ -2098,3 +2101,108 @@ func TestTeleportProcessAuthVersionUpgradeCheck(t *testing.T) {
})
}
}

type mockDatabaseObjectImportRules struct {
services.DatabaseObjectImportRules
listRules []*dbobjectimportrulev1.DatabaseObjectImportRule
created *dbobjectimportrulev1.DatabaseObjectImportRule
upserted *dbobjectimportrulev1.DatabaseObjectImportRule
}

func (m *mockDatabaseObjectImportRules) ListDatabaseObjectImportRules(context.Context, int, string) ([]*dbobjectimportrulev1.DatabaseObjectImportRule, string, error) {
return m.listRules, "", nil
}
func (m *mockDatabaseObjectImportRules) CreateDatabaseObjectImportRule(ctx context.Context, rule *dbobjectimportrulev1.DatabaseObjectImportRule) (*dbobjectimportrulev1.DatabaseObjectImportRule, error) {
m.created = rule
return rule, nil
}
func (m *mockDatabaseObjectImportRules) UpsertDatabaseObjectImportRule(ctx context.Context, rule *dbobjectimportrulev1.DatabaseObjectImportRule) (*dbobjectimportrulev1.DatabaseObjectImportRule, error) {
m.upserted = rule
return rule, nil
}

func Test_createPresetDatabaseObjectImportRule(t *testing.T) {
presetRule := databaseobjectimportrule.NewPresetImportAllObjectsRule()
require.NotNil(t, presetRule)

customRule, err := databaseobjectimportrule.NewDatabaseObjectImportRule("dev_rule", &dbobjectimportrulev1.DatabaseObjectImportRuleSpec{
Priority: 100,
DatabaseLabels: label.FromMap(map[string][]string{"env": {"dev"}}),
Mappings: []*dbobjectimportrulev1.DatabaseObjectImportRuleMapping{{
Match: &dbobjectimportrulev1.DatabaseObjectImportMatch{
TableNames: []string{"*"},
},
AddLabels: map[string]string{
"env": "dev",
},
Scope: &dbobjectimportrulev1.DatabaseObjectImportScope{
SchemaNames: []string{"public"},
},
}},
})
require.NoError(t, err)

oldPresetRule, err := databaseobjectimportrule.NewDatabaseObjectImportRule("import_all_objects", &dbobjectimportrulev1.DatabaseObjectImportRuleSpec{
DatabaseLabels: label.FromMap(map[string][]string{"*": {"*"}}),
Mappings: []*dbobjectimportrulev1.DatabaseObjectImportRuleMapping{
{
Match: &dbobjectimportrulev1.DatabaseObjectImportMatch{TableNames: []string{"*"}},
AddLabels: map[string]string{"kind": "table"},
},
{
Match: &dbobjectimportrulev1.DatabaseObjectImportMatch{ViewNames: []string{"*"}},
AddLabels: map[string]string{"kind": "view"},
},
{
Match: &dbobjectimportrulev1.DatabaseObjectImportMatch{ProcedureNames: []string{"*"}},
AddLabels: map[string]string{"kind": "procedure"},
},
},
})
require.NoError(t, err)

tests := []struct {
name string
existingRules []*dbobjectimportrulev1.DatabaseObjectImportRule
expectCreate *dbobjectimportrulev1.DatabaseObjectImportRule
expectUpsert *dbobjectimportrulev1.DatabaseObjectImportRule
}{
{
name: "create preset in new cluster",
expectCreate: presetRule,
},
{
name: "no action with custom rule",
existingRules: []*dbobjectimportrulev1.DatabaseObjectImportRule{customRule},
},
{
name: "no action with old preset and custom rule",
existingRules: []*dbobjectimportrulev1.DatabaseObjectImportRule{oldPresetRule, customRule},
},
{
name: "no action with preset rule",
existingRules: []*dbobjectimportrulev1.DatabaseObjectImportRule{presetRule},
},
{
name: "migrate old preset to new",
existingRules: []*dbobjectimportrulev1.DatabaseObjectImportRule{oldPresetRule},
expectUpsert: presetRule,
},
}

for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()

m := &mockDatabaseObjectImportRules{
listRules: test.existingRules,
}

err := createPresetDatabaseObjectImportRule(context.Background(), m)
require.NoError(t, err)
require.Equal(t, test.expectCreate, m.created)
require.Equal(t, test.expectUpsert, m.upserted)
})
}
}
40 changes: 38 additions & 2 deletions lib/srv/db/common/databaseobjectimportrule/preset.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
package databaseobjectimportrule

import (
log "github.com/sirupsen/logrus"
"context"
"log/slog"

"google.golang.org/protobuf/proto"

dbobjectimportrulev1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobjectimportrule/v1"
"github.com/gravitational/teleport/api/types/label"
Expand Down Expand Up @@ -49,8 +52,41 @@ func NewPresetImportAllObjectsRule() *dbobjectimportrulev1pb.DatabaseObjectImpor
})

if err != nil {
log.WithError(err).Warn("failed to create import_all_objects database object import rule")
slog.WarnContext(context.Background(), "failed to create import_all_objects database object import rule", "error", err)
return nil
}
return rule
}

// IsOldImportAllObjectsRulePreset checks if the provided rule is the "old" preset.
// TODO(greedy52) DELETE in 18.0
func IsOldImportAllObjectsRulePreset(cur *dbobjectimportrulev1pb.DatabaseObjectImportRule) bool {
// Make the old preset from https://github.com/gravitational/teleport/pull/37808
old, err := NewDatabaseObjectImportRule("import_all_objects", &dbobjectimportrulev1pb.DatabaseObjectImportRuleSpec{
Priority: 0,
DatabaseLabels: label.FromMap(map[string][]string{"*": {"*"}}),
Mappings: []*dbobjectimportrulev1pb.DatabaseObjectImportRuleMapping{
{
Match: &dbobjectimportrulev1pb.DatabaseObjectImportMatch{TableNames: []string{"*"}},
AddLabels: map[string]string{"kind": ObjectKindTable},
},
{
Match: &dbobjectimportrulev1pb.DatabaseObjectImportMatch{ViewNames: []string{"*"}},
AddLabels: map[string]string{"kind": ObjectKindView},
},
{
Match: &dbobjectimportrulev1pb.DatabaseObjectImportMatch{ProcedureNames: []string{"*"}},
AddLabels: map[string]string{"kind": ObjectKindProcedure},
},
},
})
if err != nil {
slog.WarnContext(context.Background(), "failed to create old import_all_objects database object import rule", "error", err)
return false
}

// Ignore these fields.
old.Metadata.Revision = cur.Metadata.Revision
old.Metadata.Namespace = cur.Metadata.Namespace
return proto.Equal(old, cur)
}

0 comments on commit 06f0b04

Please sign in to comment.