diff --git a/cmd/pbm-agent/agent.go b/cmd/pbm-agent/agent.go index 9e2781cae..fb69406a9 100644 --- a/cmd/pbm-agent/agent.go +++ b/cmd/pbm-agent/agent.go @@ -8,8 +8,8 @@ import ( "sync/atomic" "time" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/config" "github.com/percona/percona-backup-mongodb/pbm/connect" @@ -115,18 +115,18 @@ func (a *Agent) CanStart(ctx context.Context) error { func (a *Agent) showIncompatibilityWarning(ctx context.Context) { if err := version.FeatureSupport(a.brief.Version).PBMSupport(); err != nil { log.FromContext(ctx). - Warning("", "", "", primitive.Timestamp{}, "WARNING: %v", err) + Warning("", "", "", bson.Timestamp{}, "WARNING: %v", err) } if a.brief.Sharded && a.brief.Version.IsShardedTimeseriesSupported() { tss, err := topo.ListShardedTimeseries(ctx, a.leadConn) if err != nil { log.FromContext(ctx). - Error("", "", "", primitive.Timestamp{}, + Error("", "", "", bson.Timestamp{}, "failed to list sharded timeseries: %v", err) } else if len(tss) != 0 { log.FromContext(ctx). - Warning("", "", "", primitive.Timestamp{}, + Warning("", "", "", bson.Timestamp{}, "WARNING: cannot backup following sharded timeseries: %s", strings.Join(tss, ", ")) } @@ -136,11 +136,11 @@ func (a *Agent) showIncompatibilityWarning(ctx context.Context) { hasConfigShard, err := topo.HasConfigShard(ctx, a.leadConn) if err != nil { log.FromContext(ctx). - Error("", "", "", primitive.Timestamp{}, + Error("", "", "", bson.Timestamp{}, "failed to check for Config Shard: %v", err) } else if hasConfigShard { log.FromContext(ctx). - Warning("", "", "", primitive.Timestamp{}, + Warning("", "", "", bson.Timestamp{}, "WARNING: selective backup and restore is not supported with Config Shard") } } @@ -267,7 +267,7 @@ func (a *Agent) HbIsRun() bool { func (a *Agent) HbStatus(ctx context.Context) { logger := log.FromContext(ctx) - l := logger.NewEvent("agentCheckup", "", "", primitive.Timestamp{}) + l := logger.NewEvent("agentCheckup", "", "", bson.Timestamp{}) ctx = log.SetLogEventToContext(ctx, l) nodeVersion, err := version.GetMongoVersion(ctx, a.nodeConn) @@ -293,7 +293,7 @@ func (a *Agent) HbStatus(ctx context.Context) { l.Debug("deleting agent status") err := topo.RemoveAgentStatus(context.Background(), a.leadConn, hb) if err != nil { - logger := logger.NewEvent("agentCheckup", "", "", primitive.Timestamp{}) + logger := logger.NewEvent("agentCheckup", "", "", bson.Timestamp{}) logger.Error("remove agent heartbeat: %v", err) } }() @@ -408,7 +408,7 @@ func updateAgentStat( func (a *Agent) warnIfParallelAgentDetected( ctx context.Context, l log.LogEvent, - lastHeartbeat primitive.Timestamp, + lastHeartbeat bson.Timestamp, ) { s, err := topo.GetAgentStatus(ctx, a.leadConn, a.brief.SetName, a.brief.Me) if err != nil { diff --git a/cmd/pbm-agent/delete.go b/cmd/pbm-agent/delete.go index 141a04f5b..59bb7ba57 100644 --- a/cmd/pbm-agent/delete.go +++ b/cmd/pbm-agent/delete.go @@ -5,7 +5,7 @@ import ( "runtime" "time" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "golang.org/x/sync/errgroup" "github.com/percona/percona-backup-mongodb/pbm/backup" @@ -185,7 +185,7 @@ func (a *Agent) DeletePITR(ctx context.Context, d *ctrl.DeletePITRCmd, opid ctrl return } - ts := primitive.Timestamp{T: uint32(t.Unix())} + ts := bson.Timestamp{T: uint32(t.Unix())} l.Info("deleting pitr chunks older than %v", t) err = a.deletePITRImpl(ctx, ts) if err != nil { @@ -292,7 +292,7 @@ func (a *Agent) Cleanup(ctx context.Context, d *ctrl.CleanupCmd, opid ctrl.OPID, } } -func (a *Agent) deletePITRImpl(ctx context.Context, ts primitive.Timestamp) error { +func (a *Agent) deletePITRImpl(ctx context.Context, ts bson.Timestamp) error { l := log.LogEventFromContext(ctx) r, err := backup.MakeCleanupInfo(ctx, a.leadConn, ts, "") diff --git a/cmd/pbm-agent/lock.go b/cmd/pbm-agent/lock.go index 739fd4287..374fd7dcc 100644 --- a/cmd/pbm-agent/lock.go +++ b/cmd/pbm-agent/lock.go @@ -3,7 +3,7 @@ package main import ( "context" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/backup" "github.com/percona/percona-backup-mongodb/pbm/ctrl" @@ -25,7 +25,7 @@ func markBcpStale(ctx context.Context, l *lock.Lock, opid string) error { return nil } - log.FromContext(ctx).Debug(string(ctrl.CmdBackup), "", opid, primitive.Timestamp{}, "mark stale meta") + log.FromContext(ctx).Debug(string(ctrl.CmdBackup), "", opid, bson.Timestamp{}, "mark stale meta") return backup.ChangeBackupStateOPID(l.Connect(), opid, defs.StatusError, "some of pbm-agents were lost during the backup") @@ -42,7 +42,7 @@ func markRestoreStale(ctx context.Context, l *lock.Lock, opid string) error { return nil } - log.FromContext(ctx).Debug(string(ctrl.CmdRestore), "", opid, primitive.Timestamp{}, "mark stale meta") + log.FromContext(ctx).Debug(string(ctrl.CmdRestore), "", opid, bson.Timestamp{}, "mark stale meta") return restore.ChangeRestoreStateOPID(ctx, l.Connect(), opid, defs.StatusError, "some of pbm-agents were lost during the restore") diff --git a/cmd/pbm-agent/main.go b/cmd/pbm-agent/main.go index 30c8adcd1..1f43c789d 100644 --- a/cmd/pbm-agent/main.go +++ b/cmd/pbm-agent/main.go @@ -13,7 +13,7 @@ import ( "github.com/mongodb/mongo-tools/common/options" "github.com/spf13/cobra" "github.com/spf13/viper" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/ctrl" @@ -194,7 +194,7 @@ func restoreFinishCommand() *cobra.Command { string(ctrl.CmdRestore), restoreName, "", - primitive.Timestamp{}, + bson.Timestamp{}, ) extFinishCmd := &restore.ExtFinishCmd{ diff --git a/cmd/pbm-agent/pitr.go b/cmd/pbm-agent/pitr.go index e1dab9136..e57f87fb6 100644 --- a/cmd/pbm-agent/pitr.go +++ b/cmd/pbm-agent/pitr.go @@ -5,8 +5,8 @@ import ( "maps" "time" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/backup" "github.com/percona/percona-backup-mongodb/pbm/config" @@ -165,7 +165,7 @@ func (a *Agent) PITR(ctx context.Context) { for { select { case <-a.closeCMD: - l.Debug(string(ctrl.CmdPITR), "", "", primitive.Timestamp{}, "stopping main loop") + l.Debug(string(ctrl.CmdPITR), "", "", bson.Timestamp{}, "stopping main loop") return default: } diff --git a/cmd/pbm-agent/profile.go b/cmd/pbm-agent/profile.go index 24aef388e..e43dadda9 100644 --- a/cmd/pbm-agent/profile.go +++ b/cmd/pbm-agent/profile.go @@ -3,7 +3,7 @@ package main import ( "context" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/config" "github.com/percona/percona-backup-mongodb/pbm/ctrl" diff --git a/cmd/pbm-agent/resync.go b/cmd/pbm-agent/resync.go index 61e1e297b..2c4cfd42c 100644 --- a/cmd/pbm-agent/resync.go +++ b/cmd/pbm-agent/resync.go @@ -3,7 +3,7 @@ package main import ( "context" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/mongo" "golang.org/x/sync/errgroup" "github.com/percona/percona-backup-mongodb/pbm/config" diff --git a/cmd/pbm-agent/setup.go b/cmd/pbm-agent/setup.go index 86ae8e499..f33f8e440 100644 --- a/cmd/pbm-agent/setup.go +++ b/cmd/pbm-agent/setup.go @@ -4,9 +4,9 @@ import ( "context" "strings" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/defs" diff --git a/cmd/pbm-speed-test/main.go b/cmd/pbm-speed-test/main.go index ae49216cf..354294d36 100644 --- a/cmd/pbm-speed-test/main.go +++ b/cmd/pbm-speed-test/main.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/compress" "github.com/percona/percona-backup-mongodb/pbm/connect" diff --git a/cmd/pbm-speed-test/speedt.go b/cmd/pbm-speed-test/speedt.go index 7b2af7097..90a352278 100644 --- a/cmd/pbm-speed-test/speedt.go +++ b/cmd/pbm-speed-test/speedt.go @@ -7,8 +7,8 @@ import ( "strings" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/compress" "github.com/percona/percona-backup-mongodb/pbm/errors" diff --git a/cmd/pbm/config.go b/cmd/pbm/config.go index ed4eb4007..cabe4b3c0 100644 --- a/cmd/pbm/config.go +++ b/cmd/pbm/config.go @@ -7,7 +7,7 @@ import ( "os" "time" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/config" "github.com/percona/percona-backup-mongodb/pbm/connect" diff --git a/cmd/pbm/delete.go b/cmd/pbm/delete.go index 972efe7ef..0bbff7492 100644 --- a/cmd/pbm/delete.go +++ b/cmd/pbm/delete.go @@ -8,7 +8,7 @@ import ( "strings" "time" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/backup" "github.com/percona/percona-backup-mongodb/pbm/connect" @@ -125,7 +125,7 @@ func deleteBackupByName(ctx context.Context, pbm *sdk.Client, d *deleteBcpOpts) } func deleteManyBackup(ctx context.Context, pbm *sdk.Client, d *deleteBcpOpts) (sdk.CommandID, error) { - var ts primitive.Timestamp + var ts bson.Timestamp ts, err := parseOlderThan(d.olderThan) if err != nil { return sdk.NoOpID, errors.Wrap(err, "parse --older-than") @@ -190,9 +190,9 @@ func deletePITR( } } - var until primitive.Timestamp + var until bson.Timestamp if d.all { - until = primitive.Timestamp{T: uint32(time.Now().UTC().Unix())} + until = bson.Timestamp{T: uint32(time.Now().UTC().Unix())} } else { var err error until, err = parseOlderThan(d.olderThan) @@ -329,10 +329,10 @@ func doCleanup(ctx context.Context, conn connect.Client, pbm *sdk.Client, d *cle return rv, err } -func parseOlderThan(s string) (primitive.Timestamp, error) { +func parseOlderThan(s string) (bson.Timestamp, error) { s = strings.TrimSpace(s) if s == "" { - return primitive.Timestamp{}, errInvalidFormat + return bson.Timestamp{}, errInvalidFormat } ts, err := parseTS(s) @@ -345,11 +345,11 @@ func parseOlderThan(s string) (primitive.Timestamp, error) { if errors.Is(err, errInvalidDuration) { err = errInvalidFormat } - return primitive.Timestamp{}, err + return bson.Timestamp{}, err } unix := time.Now().UTC().Add(-dur).Unix() - return primitive.Timestamp{T: uint32(unix), I: 0}, nil + return bson.Timestamp{T: uint32(unix), I: 0}, nil } var errInvalidDuration = errors.New("invalid duration") @@ -394,7 +394,7 @@ func printDeleteInfoTo(w io.Writer, backups []backup.BackupMeta, chunks []oplog. } type oplogRange struct { - Start, End primitive.Timestamp + Start, End bson.Timestamp } oplogRanges := make(map[string][]oplogRange) diff --git a/cmd/pbm/diagnostic.go b/cmd/pbm/diagnostic.go index fdc174daa..8c3d88356 100644 --- a/cmd/pbm/diagnostic.go +++ b/cmd/pbm/diagnostic.go @@ -8,7 +8,7 @@ import ( "os" "path/filepath" - "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/backup" "github.com/percona/percona-backup-mongodb/pbm/errors" diff --git a/cmd/pbm/list.go b/cmd/pbm/list.go index d0fdc1273..b141eec95 100644 --- a/cmd/pbm/list.go +++ b/cmd/pbm/list.go @@ -8,7 +8,7 @@ import ( "strings" "time" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/backup" "github.com/percona/percona-backup-mongodb/pbm/config" @@ -447,38 +447,38 @@ func getBaseSnapshotLastWrite( sh map[string]bool, rsMap map[string]string, tl oplog.Timeline, -) (primitive.Timestamp, error) { - bcp, err := backup.GetFirstBackup(ctx, conn, &primitive.Timestamp{T: tl.Start, I: 0}) +) (bson.Timestamp, error) { + bcp, err := backup.GetFirstBackup(ctx, conn, &bson.Timestamp{T: tl.Start, I: 0}) if err != nil { if !errors.Is(err, errors.ErrNotFound) { - return primitive.Timestamp{}, errors.Wrapf(err, "get backup for timeline: %s", tl) + return bson.Timestamp{}, errors.Wrapf(err, "get backup for timeline: %s", tl) } - return primitive.Timestamp{}, nil + return bson.Timestamp{}, nil } if bcp == nil { - return primitive.Timestamp{}, nil + return bson.Timestamp{}, nil } ver, err := version.GetMongoVersion(ctx, conn.MongoClient()) if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "get mongo version") + return bson.Timestamp{}, errors.Wrap(err, "get mongo version") } fcv, err := version.GetFCV(ctx, conn.MongoClient()) if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "get featureCompatibilityVersion") + return bson.Timestamp{}, errors.Wrap(err, "get featureCompatibilityVersion") } bcpMatchCluster(bcp, ver.VersionString, fcv, sh, util.MakeRSMapFunc(rsMap), util.MakeReverseRSMapFunc(rsMap)) if bcp.Status != defs.StatusDone { - return primitive.Timestamp{}, nil + return bson.Timestamp{}, nil } return bcp.LastWriteTS, nil } -func splitByBaseSnapshot(lastWrite primitive.Timestamp, tl oplog.Timeline) []pitrRange { +func splitByBaseSnapshot(lastWrite bson.Timestamp, tl oplog.Timeline) []pitrRange { if lastWrite.IsZero() || (lastWrite.T < tl.Start || lastWrite.T > tl.End) { return []pitrRange{{Range: tl, NoBaseSnapshot: true}} } diff --git a/cmd/pbm/list_test.go b/cmd/pbm/list_test.go index 54a127d17..92ff5404c 100644 --- a/cmd/pbm/list_test.go +++ b/cmd/pbm/list_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/oplog" ) @@ -13,7 +13,7 @@ func Test_splitByBaseSnapshot(t *testing.T) { tl := oplog.Timeline{Start: 3, End: 7} t.Run("lastWrite is nil", func(t *testing.T) { - lastWrite := primitive.Timestamp{} + lastWrite := bson.Timestamp{} got := splitByBaseSnapshot(lastWrite, tl) want := []pitrRange{ @@ -24,7 +24,7 @@ func Test_splitByBaseSnapshot(t *testing.T) { }) t.Run("lastWrite > tl.End", func(t *testing.T) { - lastWrite := primitive.Timestamp{T: tl.End + 1} + lastWrite := bson.Timestamp{T: tl.End + 1} got := splitByBaseSnapshot(lastWrite, tl) want := []pitrRange{ @@ -35,7 +35,7 @@ func Test_splitByBaseSnapshot(t *testing.T) { }) t.Run("lastWrite = tl.End", func(t *testing.T) { - lastWrite := primitive.Timestamp{T: tl.End} + lastWrite := bson.Timestamp{T: tl.End} got := splitByBaseSnapshot(lastWrite, tl) want := []pitrRange{ @@ -46,7 +46,7 @@ func Test_splitByBaseSnapshot(t *testing.T) { }) t.Run("lastWrite < tl.Start", func(t *testing.T) { - lastWrite := primitive.Timestamp{T: tl.Start - 1} + lastWrite := bson.Timestamp{T: tl.Start - 1} got := splitByBaseSnapshot(lastWrite, tl) want := []pitrRange{ @@ -57,7 +57,7 @@ func Test_splitByBaseSnapshot(t *testing.T) { }) t.Run("lastWrite = tl.Start", func(t *testing.T) { - lastWrite := primitive.Timestamp{T: tl.Start} + lastWrite := bson.Timestamp{T: tl.Start} got := splitByBaseSnapshot(lastWrite, tl) want := []pitrRange{ @@ -74,7 +74,7 @@ func Test_splitByBaseSnapshot(t *testing.T) { }) t.Run("tl.Start < lastWrite < tl.End", func(t *testing.T) { - lastWrite := primitive.Timestamp{T: 5} + lastWrite := bson.Timestamp{T: 5} got := splitByBaseSnapshot(lastWrite, tl) want := []pitrRange{ diff --git a/cmd/pbm/profile.go b/cmd/pbm/profile.go index 0339f2abc..de6f3a880 100644 --- a/cmd/pbm/profile.go +++ b/cmd/pbm/profile.go @@ -7,7 +7,7 @@ import ( "strings" "time" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/config" "github.com/percona/percona-backup-mongodb/pbm/errors" diff --git a/cmd/pbm/restore.go b/cmd/pbm/restore.go index d13f64e79..266a000a0 100644 --- a/cmd/pbm/restore.go +++ b/cmd/pbm/restore.go @@ -11,8 +11,7 @@ import ( "time" "github.com/mongodb/mongo-tools/common/db" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "gopkg.in/yaml.v2" "github.com/percona/percona-backup-mongodb/pbm/backup" @@ -403,13 +402,13 @@ func checkBackup( return "", "", errors.Errorf("backup '%s' not found", b) } } else { - var ts primitive.Timestamp + var ts bson.Timestamp ts, err = parseTS(o.pitr) if err != nil { return "", "", errors.Wrap(err, "parse pitr") } - bcp, err = backup.GetLastBackup(ctx, conn, &primitive.Timestamp{T: ts.T + 1, I: 0}) + bcp, err = backup.GetLastBackup(ctx, conn, &bson.Timestamp{T: ts.T + 1, I: 0}) if errors.Is(err, errors.ErrNotFound) { return "", "", errors.New("no base snapshot found") } @@ -579,8 +578,8 @@ func runFinishRestore(o descrRestoreOpts, node string) (fmt.Stringer, error) { return msg, err } -func parseTS(t string) (primitive.Timestamp, error) { - var ts primitive.Timestamp +func parseTS(t string) (bson.Timestamp, error) { + var ts bson.Timestamp if si := strings.SplitN(t, ",", 2); len(si) == 2 { tt, err := strconv.ParseInt(si[0], 10, 64) if err != nil { @@ -591,7 +590,7 @@ func parseTS(t string) (primitive.Timestamp, error) { return ts, errors.Wrap(err, "parse clusterTime I") } - return primitive.Timestamp{T: uint32(tt), I: uint32(ti)}, nil + return bson.Timestamp{T: uint32(tt), I: uint32(ti)}, nil } tsto, err := parseDateT(t) @@ -599,7 +598,7 @@ func parseTS(t string) (primitive.Timestamp, error) { return ts, errors.Wrap(err, "parse date") } - return primitive.Timestamp{T: uint32(tsto.Unix()), I: 0}, nil + return bson.Timestamp{T: uint32(tsto.Unix()), I: 0}, nil } type getRestoreMetaFn func(ctx context.Context, conn connect.Client, name string) (*restore.RestoreMeta, error) @@ -773,7 +772,7 @@ func describeRestore( return nil, errors.Wrap(err, "get storage") } meta, err = restore.GetPhysRestoreMeta(o.restore, stg, log.New(nil, "cli", ""). - NewEvent("", "", "", primitive.Timestamp{})) + NewEvent("", "", "", bson.Timestamp{})) if err != nil && meta == nil { return nil, errors.Wrap(err, "get restore meta") } diff --git a/cmd/pbm/status.go b/cmd/pbm/status.go index 29b5f025d..6756b2467 100644 --- a/cmd/pbm/status.go +++ b/cmd/pbm/status.go @@ -9,7 +9,7 @@ import ( "strings" "time" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/backup" "github.com/percona/percona-backup-mongodb/pbm/config" @@ -136,7 +136,7 @@ func status( } var sfilter map[string]bool - if opts.sections != nil && len(opts.sections) > 0 { + if len(opts.sections) > 0 { sfilter = make(map[string]bool) for _, s := range opts.sections { sfilter[s] = true @@ -604,7 +604,7 @@ func getStorageStat( bcpsMatchCluster(bcps, ver.VersionString, fcv, shards, rsMap) stg, err := util.GetStorage(ctx, conn, inf.Me, - log.FromContext(ctx).NewEvent("", "", "", primitive.Timestamp{})) + log.FromContext(ctx).NewEvent("", "", "", bson.Timestamp{})) if err != nil { return s, errors.Wrap(err, "get storage") } @@ -716,7 +716,7 @@ func getPITRranges( var pr []pitrRange for _, tl := range oplog.MergeTimelines(rstlines...) { - var bcplastWrite primitive.Timestamp + var bcplastWrite bson.Timestamp for i := range bcps { bcp := &bcps[i] diff --git a/e2e-tests/cmd/ensure-oplog/main.go b/e2e-tests/cmd/ensure-oplog/main.go index 2d39d014b..56017f2b4 100644 --- a/e2e-tests/cmd/ensure-oplog/main.go +++ b/e2e-tests/cmd/ensure-oplog/main.go @@ -11,10 +11,9 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" "golang.org/x/sync/errgroup" "github.com/percona/percona-backup-mongodb/pbm/compress" @@ -122,8 +121,8 @@ func connTopo(ctx context.Context, uri string) (topo, error) { return topoUnknown, nil } -func parseTS(t string) (primitive.Timestamp, error) { - var ts primitive.Timestamp +func parseTS(t string) (bson.Timestamp, error) { + var ts bson.Timestamp if len(t) == 0 { return ts, nil } @@ -181,7 +180,7 @@ func sayHello(ctx context.Context, m *mongo.Client) (*hello, error) { return r, errors.Wrap(err, "decode") } -func ensureClusterOplog(ctx context.Context, uri string, from, till primitive.Timestamp) error { +func ensureClusterOplog(ctx context.Context, uri string, from, till bson.Timestamp) error { logger.Printf("[%s] ensuring cluster oplog: %s - %s", uri, formatTimestamp(from), formatTimestamp(from)) @@ -221,7 +220,7 @@ func ensureClusterOplog(ctx context.Context, uri string, from, till primitive.Ti return nil } -func ensureReplsetOplog(ctx context.Context, uri string, from, till primitive.Timestamp) error { +func ensureReplsetOplog(ctx context.Context, uri string, from, till bson.Timestamp) error { logger.Printf("[%s] ensure replset oplog: %s - %s", uri, formatTimestamp(from), formatTimestamp(from)) @@ -325,7 +324,7 @@ func ensureReplsetOplog(ctx context.Context, uri string, from, till primitive.Ti return nil } -func findPreviousOplogTS(ctx context.Context, m *mongo.Client, ts primitive.Timestamp) (primitive.Timestamp, error) { +func findPreviousOplogTS(ctx context.Context, m *mongo.Client, ts bson.Timestamp) (bson.Timestamp, error) { f := bson.M{} if !ts.IsZero() { f["ts"] = bson.M{"$lte": ts} @@ -335,7 +334,7 @@ func findPreviousOplogTS(ctx context.Context, m *mongo.Client, ts primitive.Time return findOplogTSHelper(res) } -func findFollowingOplogTS(ctx context.Context, m *mongo.Client, ts primitive.Timestamp) (primitive.Timestamp, error) { +func findFollowingOplogTS(ctx context.Context, m *mongo.Client, ts bson.Timestamp) (bson.Timestamp, error) { f := bson.M{} if !ts.IsZero() { f["ts"] = bson.M{"$gte": ts} @@ -345,24 +344,24 @@ func findFollowingOplogTS(ctx context.Context, m *mongo.Client, ts primitive.Tim return findOplogTSHelper(res) } -func findOplogTSHelper(res *mongo.SingleResult) (primitive.Timestamp, error) { +func findOplogTSHelper(res *mongo.SingleResult) (bson.Timestamp, error) { if err := res.Err(); err != nil { - return primitive.Timestamp{}, err + return bson.Timestamp{}, err } - var v struct{ TS primitive.Timestamp } + var v struct{ TS bson.Timestamp } if err := res.Decode(&v); err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "decode") + return bson.Timestamp{}, errors.Wrap(err, "decode") } return v.TS, nil } type timerange struct { - from, till primitive.Timestamp + from, till bson.Timestamp } -func findChunkRanges(rs []oplog.OplogChunk, from, till primitive.Timestamp) []timerange { +func findChunkRanges(rs []oplog.OplogChunk, from, till bson.Timestamp) []timerange { if len(rs) == 0 { return []timerange{{from, till}} } @@ -393,6 +392,6 @@ func findChunkRanges(rs []oplog.OplogChunk, from, till primitive.Timestamp) []ti return rv } -func formatTimestamp(t primitive.Timestamp) string { +func formatTimestamp(t bson.Timestamp) string { return fmt.Sprintf("%d,%d", t.T, t.I) } diff --git a/e2e-tests/cmd/pbm-test/run.go b/e2e-tests/cmd/pbm-test/run.go index 4431c80e2..e2b52add8 100644 --- a/e2e-tests/cmd/pbm-test/run.go +++ b/e2e-tests/cmd/pbm-test/run.go @@ -115,11 +115,11 @@ func run(t *sharded.Cluster, typ testTyp) { t.CleanupFullRestore) // disttxnconf := "/etc/pbm/fs-disttxn-4x.yaml" - // tsTo := primitive.Timestamp{1644410656, 8} + // tsTo := bson.Timestamp{1644410656, 8} //if semver.Compare(cVersion, "v5.0") >= 0 { // disttxnconf = "/etc/pbm/fs-disttxn-50.yaml" - // tsTo = primitive.Timestamp{1644243375, 7} + // tsTo = bson.Timestamp{1644243375, 7} //} // t.ApplyConfig(context.TODO(), disttxnconf) diff --git a/e2e-tests/pkg/pbm/mongo_pbm.go b/e2e-tests/pkg/pbm/mongo_pbm.go index 9761b506a..2b765a4ec 100644 --- a/e2e-tests/pkg/pbm/mongo_pbm.go +++ b/e2e-tests/pkg/pbm/mongo_pbm.go @@ -4,8 +4,8 @@ import ( "context" "time" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/backup" "github.com/percona/percona-backup-mongodb/pbm/config" @@ -50,20 +50,20 @@ func (m *MongoPBM) GetBackupMeta(ctx context.Context, bcpName string) (*backup.B func (m *MongoPBM) DeleteBackup(ctx context.Context, bcpName string) error { l := log.FromContext(ctx). - NewEvent(string(ctrl.CmdDeleteBackup), "", "", primitive.Timestamp{}) + NewEvent(string(ctrl.CmdDeleteBackup), "", "", bson.Timestamp{}) ctx = log.SetLogEventToContext(ctx, l) return backup.DeleteBackup(ctx, m.conn, bcpName, "") } func (m *MongoPBM) Storage(ctx context.Context) (storage.Storage, error) { l := log.FromContext(ctx). - NewEvent("", "", "", primitive.Timestamp{}) + NewEvent("", "", "", bson.Timestamp{}) return util.GetStorage(ctx, m.conn, "", l) } func (m *MongoPBM) StoreResync(ctx context.Context) error { l := log.FromContext(ctx). - NewEvent(string(ctrl.CmdResync), "", "", primitive.Timestamp{}) + NewEvent(string(ctrl.CmdResync), "", "", bson.Timestamp{}) ctx = log.SetLogEventToContext(ctx, l) cfg, err := config.GetConfig(ctx, m.conn) diff --git a/e2e-tests/pkg/pbm/mongod.go b/e2e-tests/pkg/pbm/mongod.go index 185cc2760..ba0fd8f7e 100644 --- a/e2e-tests/pkg/pbm/mongod.go +++ b/e2e-tests/pkg/pbm/mongod.go @@ -6,10 +6,9 @@ import ( "math/rand" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/errors" @@ -172,7 +171,7 @@ type Counter struct { Count int WallTime time.Time ID interface{} - WriteTime primitive.Timestamp + WriteTime bson.Timestamp } func (c Counter) String() string { @@ -264,13 +263,13 @@ func (m *Mongo) GetNodeInfo() (*topo.NodeInfo, error) { return inf, nil } -func (m *Mongo) GetLastWrite() (primitive.Timestamp, error) { +func (m *Mongo) GetLastWrite() (bson.Timestamp, error) { inf, err := m.GetNodeInfo() if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "get NodeInfo data") + return bson.Timestamp{}, errors.Wrap(err, "get NodeInfo data") } if inf.LastWrite.MajorityOpTime.TS.T == 0 { - return primitive.Timestamp{}, errors.New("timestamp is nil") + return bson.Timestamp{}, errors.New("timestamp is nil") } return inf.LastWrite.OpTime.TS, nil } diff --git a/e2e-tests/pkg/tests/data.go b/e2e-tests/pkg/tests/data.go index ea82d2d68..290b48d21 100644 --- a/e2e-tests/pkg/tests/data.go +++ b/e2e-tests/pkg/tests/data.go @@ -6,8 +6,8 @@ import ( "runtime" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "golang.org/x/sync/errgroup" "github.com/percona/percona-backup-mongodb/pbm/errors" diff --git a/e2e-tests/pkg/tests/sharded/cluster.go b/e2e-tests/pkg/tests/sharded/cluster.go index 8fb6b0f83..6100c10e5 100644 --- a/e2e-tests/pkg/tests/sharded/cluster.go +++ b/e2e-tests/pkg/tests/sharded/cluster.go @@ -7,8 +7,7 @@ import ( stdlog "log" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" pbmt "github.com/percona/percona-backup-mongodb/e2e-tests/pkg/pbm" "github.com/percona/percona-backup-mongodb/pbm/ctrl" @@ -283,7 +282,7 @@ func getRestoreMetaStg(name string, stg storage.Storage) (*restore.RestoreMeta, return rmeta, nil } -func (c *Cluster) PITRestoreCT(t primitive.Timestamp) { +func (c *Cluster) PITRestoreCT(t bson.Timestamp) { stdlog.Printf("restoring to the point-in-time %v", t) err := c.pbm.PITRestoreClusterTime(t.T, t.I) if err != nil { diff --git a/e2e-tests/pkg/tests/sharded/cmd.go b/e2e-tests/pkg/tests/sharded/cmd.go index 96c6e62b8..54d74846c 100644 --- a/e2e-tests/pkg/tests/sharded/cmd.go +++ b/e2e-tests/pkg/tests/sharded/cmd.go @@ -4,8 +4,8 @@ import ( "context" "log" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" ) func (c *Cluster) stopBalancer(ctx context.Context, conn *mongo.Client) { diff --git a/e2e-tests/pkg/tests/sharded/test_bounds_check.go b/e2e-tests/pkg/tests/sharded/test_bounds_check.go index f7c3017a4..4c9001ec4 100644 --- a/e2e-tests/pkg/tests/sharded/test_bounds_check.go +++ b/e2e-tests/pkg/tests/sharded/test_bounds_check.go @@ -6,7 +6,7 @@ import ( "math/rand" "time" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "golang.org/x/mod/semver" pbmt "github.com/percona/percona-backup-mongodb/e2e-tests/pkg/pbm" @@ -18,11 +18,11 @@ type scounter struct { cancel context.CancelFunc } -func lte(t1, t2 primitive.Timestamp) bool { +func lte(t1, t2 bson.Timestamp) bool { return t1.Compare(t2) <= 0 } -func lt(t1, t2 primitive.Timestamp) bool { +func lt(t1, t2 bson.Timestamp) bool { return t1.Compare(t2) < 0 } @@ -133,8 +133,8 @@ func (c *Cluster) bcheckCheck( name string, shard *pbmt.Mongo, data *[]pbmt.Counter, - bcpLastWrite primitive.Timestamp, - inRange func(ts, limit primitive.Timestamp) bool, + bcpLastWrite bson.Timestamp, + inRange func(ts, limit bson.Timestamp) bool, ) { log.Println(name, "getting restored counters") restored, err := shard.GetCounters() diff --git a/e2e-tests/pkg/tests/sharded/test_cleanup_full_restore.go b/e2e-tests/pkg/tests/sharded/test_cleanup_full_restore.go index dd2b2d06c..1125bb203 100644 --- a/e2e-tests/pkg/tests/sharded/test_cleanup_full_restore.go +++ b/e2e-tests/pkg/tests/sharded/test_cleanup_full_restore.go @@ -5,8 +5,8 @@ import ( "fmt" "log" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" ) func (c *Cluster) CleanupFullRestore() { diff --git a/e2e-tests/pkg/tests/sharded/test_dist_commit.go b/e2e-tests/pkg/tests/sharded/test_dist_commit.go index 9020e0378..8e54954dd 100644 --- a/e2e-tests/pkg/tests/sharded/test_dist_commit.go +++ b/e2e-tests/pkg/tests/sharded/test_dist_commit.go @@ -4,12 +4,11 @@ import ( "context" "log" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" ) -func (c *Cluster) DistributedCommit(restoreTo primitive.Timestamp) { - // c.PITRestoreCT(primitive.Timestamp{1644243375, 7}) +func (c *Cluster) DistributedCommit(restoreTo bson.Timestamp) { + // c.PITRestoreCT(bson.Timestamp{1644243375, 7}) c.PITRestoreCT(restoreTo) exp := map[int]bool{ diff --git a/e2e-tests/pkg/tests/sharded/test_oplog_replay.go b/e2e-tests/pkg/tests/sharded/test_oplog_replay.go index 56afd60fa..b9dd13b5d 100644 --- a/e2e-tests/pkg/tests/sharded/test_oplog_replay.go +++ b/e2e-tests/pkg/tests/sharded/test_oplog_replay.go @@ -6,7 +6,7 @@ import ( "math/rand" "time" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" tpbm "github.com/percona/percona-backup-mongodb/e2e-tests/pkg/pbm" ) @@ -95,6 +95,6 @@ func getLastWrittenCounter(counters map[string]shardCounter) tpbm.Counter { return *rv } -func getLastWriteTime(counters map[string]shardCounter) primitive.Timestamp { +func getLastWriteTime(counters map[string]shardCounter) bson.Timestamp { return getLastWrittenCounter(counters).WriteTime } diff --git a/e2e-tests/pkg/tests/sharded/test_pitr_basic.go b/e2e-tests/pkg/tests/sharded/test_pitr_basic.go index a1904e021..4b8b9122d 100644 --- a/e2e-tests/pkg/tests/sharded/test_pitr_basic.go +++ b/e2e-tests/pkg/tests/sharded/test_pitr_basic.go @@ -7,7 +7,7 @@ import ( "sync" "time" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" pbmt "github.com/percona/percona-backup-mongodb/e2e-tests/pkg/pbm" "github.com/percona/percona-backup-mongodb/pbm/ctrl" @@ -161,7 +161,7 @@ func (pc *pcounter) current() *pbmt.Counter { return pc.curr } -func (c *Cluster) pitrcCheck(name string, shard *pbmt.Mongo, data *[]pbmt.Counter, bcpLastWrite primitive.Timestamp) { +func (c *Cluster) pitrcCheck(name string, shard *pbmt.Mongo, data *[]pbmt.Counter, bcpLastWrite bson.Timestamp) { log.Println(name, "getting restored counters") restored, err := shard.GetCounters() if err != nil { diff --git a/e2e-tests/pkg/tests/sharded/trx.go b/e2e-tests/pkg/tests/sharded/trx.go index 8191f9319..c5f59f75e 100644 --- a/e2e-tests/pkg/tests/sharded/trx.go +++ b/e2e-tests/pkg/tests/sharded/trx.go @@ -6,12 +6,12 @@ import ( "strings" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" - "go.mongodb.org/mongo-driver/mongo/readconcern" - "go.mongodb.org/mongo-driver/mongo/readpref" - "go.mongodb.org/mongo-driver/mongo/writeconcern" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" + "go.mongodb.org/mongo-driver/v2/mongo/readconcern" + "go.mongodb.org/mongo-driver/v2/mongo/readpref" + "go.mongodb.org/mongo-driver/v2/mongo/writeconcern" pbmt "github.com/percona/percona-backup-mongodb/e2e-tests/pkg/pbm" ) @@ -76,10 +76,14 @@ func (c *Cluster) DistributedTransactions(bcp Backuper, col string) { sess, err := conn.StartSession( options.Session(). - SetDefaultReadPreference(readpref.Primary()). SetCausalConsistency(true). - SetDefaultReadConcern(readconcern.Majority()). - SetDefaultWriteConcern(writeconcern.Majority())) + SetDefaultTransactionOptions( + options.Transaction(). + SetReadPreference(readpref.Primary()). + SetReadConcern(readconcern.Majority()). + SetWriteConcern(writeconcern.Majority()), + ), + ) if err != nil { log.Fatalln("ERROR: start session:", err) } @@ -105,7 +109,7 @@ func (c *Cluster) DistributedTransactions(bcp Backuper, col string) { // distributed transaction that commits before the backup ends // should be visible after restore log.Println("Run trx1") - _, _ = sess.WithTransaction(ctx, func(sc mongo.SessionContext) (interface{}, error) { + _, _ = sess.WithTransaction(ctx, func(sc context.Context) (interface{}, error) { c.trxSet(sc, 30, col) c.trxSet(sc, 530, col) @@ -129,7 +133,7 @@ func (c *Cluster) DistributedTransactions(bcp Backuper, col string) { log.Println("Run trx2") // distributed transaction that commits after the backup ends // should NOT be visible after the restore - _ = mongo.WithSession(ctx, sess, func(sc mongo.SessionContext) error { + _ = mongo.WithSession(ctx, sess, func(sc context.Context) error { err := sess.StartTransaction() if err != nil { log.Fatalln("ERROR: start transaction:", err) @@ -172,7 +176,7 @@ func (c *Cluster) DistributedTransactions(bcp Backuper, col string) { c.checkTrxCollection(ctx, col, bcp) } -func (c *Cluster) trxSet(ctx mongo.SessionContext, id int, col string) { +func (c *Cluster) trxSet(ctx context.Context, id int, col string) { log.Print("\ttrx", id) err := c.updateTrxRetry(ctx, col, bson.M{"idx": id}, bson.D{{"$set", bson.M{"changed": 1}}}) if err != nil { @@ -182,7 +186,7 @@ func (c *Cluster) trxSet(ctx mongo.SessionContext, id int, col string) { // updateTrxRetry tries to run an update operation and in case of the StaleConfig error // it run flushRouterConfig and tries again -func (c *Cluster) updateTrxRetry(ctx mongo.SessionContext, col string, filter, update interface{}) error { +func (c *Cluster) updateTrxRetry(ctx context.Context, col string, filter, update interface{}) error { var err error conn := c.mongos.Conn() for i := 0; i < 3; i++ { diff --git a/e2e-tests/pkg/tests/sharded/trx_phys.go b/e2e-tests/pkg/tests/sharded/trx_phys.go index a96eadc28..ce3dd9c65 100644 --- a/e2e-tests/pkg/tests/sharded/trx_phys.go +++ b/e2e-tests/pkg/tests/sharded/trx_phys.go @@ -4,12 +4,12 @@ import ( "context" "log" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" - "go.mongodb.org/mongo-driver/mongo/readconcern" - "go.mongodb.org/mongo-driver/mongo/readpref" - "go.mongodb.org/mongo-driver/mongo/writeconcern" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" + "go.mongodb.org/mongo-driver/v2/mongo/readconcern" + "go.mongodb.org/mongo-driver/v2/mongo/readpref" + "go.mongodb.org/mongo-driver/v2/mongo/writeconcern" ) func (c *Cluster) DistributedTransactionsPhys(bcp Backuper, col string) { @@ -53,10 +53,14 @@ func (c *Cluster) DistributedTransactionsPhys(bcp Backuper, col string) { sess, err := conn.StartSession( options.Session(). - SetDefaultReadPreference(readpref.Primary()). SetCausalConsistency(true). - SetDefaultReadConcern(readconcern.Majority()). - SetDefaultWriteConcern(writeconcern.Majority())) + SetDefaultTransactionOptions( + options.Transaction(). + SetReadPreference(readpref.Primary()). + SetReadConcern(readconcern.Majority()). + SetWriteConcern(writeconcern.Majority()), + ), + ) if err != nil { log.Fatalln("ERROR: start session:", err) } @@ -82,7 +86,7 @@ func (c *Cluster) DistributedTransactionsPhys(bcp Backuper, col string) { // distributed transaction that commits before the backup ends // should be visible after restore log.Println("Run trx1") - _, _ = sess.WithTransaction(ctx, func(sc mongo.SessionContext) (interface{}, error) { + _, _ = sess.WithTransaction(ctx, func(sc context.Context) (interface{}, error) { c.trxSet(sc, 30, col) c.trxSet(sc, 530, col) c.trxSet(sc, 130, col) @@ -102,7 +106,7 @@ func (c *Cluster) DistributedTransactionsPhys(bcp Backuper, col string) { log.Println("Run trx2") // distributed transaction that commits after the backup ends // should NOT be visible after the restore - _ = mongo.WithSession(ctx, sess, func(sc mongo.SessionContext) error { + _ = mongo.WithSession(ctx, sess, func(sc context.Context) error { err := sess.StartTransaction() if err != nil { log.Fatalln("ERROR: start transaction:", err) diff --git a/e2e-tests/pkg/tests/state.go b/e2e-tests/pkg/tests/state.go index eab46606f..2726b46bf 100644 --- a/e2e-tests/pkg/tests/state.go +++ b/e2e-tests/pkg/tests/state.go @@ -11,9 +11,8 @@ import ( "strings" "sync" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "golang.org/x/sync/errgroup" "github.com/percona/percona-backup-mongodb/pbm/connect" @@ -55,9 +54,9 @@ type dbSpec struct { ID string `bson:"_id"` Primary string `bson:"primary"` Version struct { - UUID primitive.Binary `bson:"uuid"` - Timestamp primitive.Timestamp `bson:"timestamp"` - LastMod int32 `bson:"lastMod,omitempty"` // since v5.0 + UUID bson.Binary `bson:"uuid"` + Timestamp bson.Timestamp `bson:"timestamp"` + LastMod int32 `bson:"lastMod,omitempty"` // since v5.0 } `bson:"version"` } @@ -72,15 +71,15 @@ type configCollState struct { // collSpec describes a sharded collection. It is a config.collections document type collSpec struct { - ID string `bson:"_id"` - LastmodEpoch primitive.ObjectID `bson:"lastmodEpoch"` - LastMod primitive.DateTime `bson:"lastMod"` - Timestamp primitive.Timestamp `bson:"timestamp"` - UUID *primitive.Binary `bson:"uuid,omitempty"` // since v5.0 - Key map[string]any `bson:"key"` - Unique bool `bson:"unique"` - ChunksSplit bool `bson:"chunksAlreadySplitForDowngrade"` - NoBalance bool `bson:"noBalance"` + ID string `bson:"_id"` + LastmodEpoch bson.ObjectID `bson:"lastmodEpoch"` + LastMod bson.DateTime `bson:"lastMod"` + Timestamp bson.Timestamp `bson:"timestamp"` + UUID *bson.Binary `bson:"uuid,omitempty"` // since v5.0 + Key map[string]any `bson:"key"` + Unique bool `bson:"unique"` + ChunksSplit bool `bson:"chunksAlreadySplitForDowngrade"` + NoBalance bool `bson:"noBalance"` } // chunksState is chunks state for a ns for a shard @@ -99,7 +98,7 @@ type shardState map[NSName]*shardCollState // shardCollState describes a collection state on a shard type shardCollState struct { // Spec is value of listCollections command - Spec *mongo.CollectionSpecification + Spec mongo.CollectionSpecification // Hash is dbHash value on a shard Hash string @@ -334,12 +333,12 @@ func getConfigChunkHashes( var f bson.D if useUUID { - in := make([]primitive.Binary, 0, len(selection)) + in := make([]bson.Binary, 0, len(selection)) for uuid := range selection { hashes[uuid] = md5.New() counts[uuid] = make(map[ShardName]int64) data, _ := hex.DecodeString(uuid) - in = append(in, primitive.Binary{Subtype: 0x4, Data: data}) + in = append(in, bson.Binary{Subtype: 0x4, Data: data}) } f = bson.D{{"uuid", bson.M{"$in": in}}} diff --git a/go.mod b/go.mod index 876115759..480281471 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/percona/percona-backup-mongodb -go 1.25.5 +go 1.25.9 require ( cloud.google.com/go/storage v1.62.1 @@ -25,7 +25,7 @@ require ( github.com/minio/minio-go/v7 v7.0.98 github.com/moby/moby/api v1.54.1 github.com/moby/moby/client v0.4.0 - github.com/mongodb/mongo-tools v0.0.0-20240723193119-837c2bc263f4 + github.com/mongodb/mongo-tools v0.0.0-20260424130528-bbe4099afe32 github.com/pierrec/lz4 v2.6.1+incompatible github.com/pkg/errors v0.9.1 github.com/spf13/cobra v1.10.2 @@ -34,7 +34,7 @@ require ( github.com/testcontainers/testcontainers-go v0.42.0 github.com/testcontainers/testcontainers-go/modules/minio v0.42.0 github.com/testcontainers/testcontainers-go/modules/mongodb v0.42.0 - go.mongodb.org/mongo-driver v1.17.9 + go.mongodb.org/mongo-driver/v2 v2.6.0 golang.org/x/mod v0.33.0 golang.org/x/oauth2 v0.36.0 golang.org/x/sync v0.20.0 @@ -51,8 +51,10 @@ require ( cloud.google.com/go/iam v1.7.0 // indirect cloud.google.com/go/monitoring v1.24.3 // indirect dario.cat/mergo v1.0.2 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect @@ -71,6 +73,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 // indirect + github.com/ccoveille/go-safecast/v2 v2.0.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // indirect @@ -80,6 +83,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-connections v0.6.0 // indirect github.com/docker/go-units v0.5.0 // indirect @@ -101,6 +105,7 @@ require ( github.com/jessevdk/go-flags v1.6.1 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/klauspost/crc32 v1.3.0 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.10 // indirect github.com/minio/crc64nvme v1.1.1 // indirect @@ -112,16 +117,17 @@ require ( github.com/moby/sys/user v0.4.0 // indirect github.com/moby/sys/userns v0.1.0 // indirect github.com/moby/term v0.5.2 // indirect - github.com/montanaflynn/stats v0.7.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/philhofer/fwd v1.2.0 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/rs/xid v1.6.0 // indirect github.com/sagikazarmark/locafero v0.12.0 // indirect + github.com/samber/lo v1.49.1 // indirect github.com/shirou/gopsutil/v4 v4.26.3 // indirect github.com/sirupsen/logrus v1.9.4 // indirect github.com/spf13/afero v1.15.0 // indirect @@ -137,7 +143,6 @@ require ( github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.40.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0 // indirect diff --git a/go.sum b/go.sum index dee8ca955..bff68a725 100644 --- a/go.sum +++ b/go.sum @@ -28,6 +28,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0 h1:fou+2+WFTib47nS+nz/ozhEB github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0/go.mod h1:t76Ruy8AHvUAC8GfMWJMa0ElSbuIcO03NLpynfbgsPA= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 h1:Hk5QBxZQC1jb2Fwj6mpzme37xbCDdNTxU7O9eb5+LB4= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1/go.mod h1:IYus9qsFobWIc2YVwe/WPjcnyCkPKtnHAqUYeebc8z0= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 h1:/Zt+cDPnpC3OVDm/JKLOs7M2DKmLRIIp3XIx9pHHiig= @@ -36,6 +38,8 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4 h1:jWQK1GI+LeGGUKBAD github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4/go.mod h1:8mwH4klAm9DUgR2EEHyEEAQlRDvLPyg5fQry3y+cDew= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs= github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 h1:DHa2U07rk8syqvCge0QIGMCE1WxGj9njT44GH7zNJLQ= @@ -96,6 +100,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 h1:5fFjR/ToSOzB2OQ/XqWpZBmNvmP/ github.com/aws/aws-sdk-go-v2/service/sts v1.41.6/go.mod h1:qgFDZQSD/Kys7nJnVqYlWKnh0SSdMjAi0uSwON4wgYQ= github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk= github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= +github.com/ccoveille/go-safecast/v2 v2.0.0 h1:+5eyITXAUj3wMjad6cRVJKGnC7vDS55zk0INzJagub0= +github.com/ccoveille/go-safecast/v2 v2.0.0/go.mod h1:JIYA4CAR33blIDuE6fSwCp2sz1oOBahXnvmdBhOAABs= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -119,6 +125,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= +github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= @@ -185,6 +193,8 @@ github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPG github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= +github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k= github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -232,10 +242,8 @@ github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mongodb/mongo-tools v0.0.0-20240723193119-837c2bc263f4 h1:23sRjM+3p+4yFL9tOg9qfNJHtBMl5PN5XA2iLWrYR+Y= -github.com/mongodb/mongo-tools v0.0.0-20240723193119-837c2bc263f4/go.mod h1:mq5q2Rrbw6+VEtDc+p5haujgWoQv3foL2YS5YISr2UA= -github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= -github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/mongodb/mongo-tools v0.0.0-20260424130528-bbe4099afe32 h1:9R7OFAMZStPFtEghvpAoDHZNEMxtSefxnVlYV7efQpA= +github.com/mongodb/mongo-tools v0.0.0-20260424130528-bbe4099afe32/go.mod h1:PySfOqUP1zoUl9n+M1sM2cUS/JzioBN7yuuK2PlRPbc= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -265,6 +273,8 @@ github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4= github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI= +github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= +github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= github.com/shirou/gopsutil/v4 v4.26.3 h1:2ESdQt90yU3oXF/CdOlRCJxrP+Am1aBYubTMTfxJ1qc= github.com/shirou/gopsutil/v4 v4.26.3/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= @@ -324,10 +334,8 @@ github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfS github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.mongodb.org/mongo-driver v1.17.9 h1:IexDdCuuNJ3BHrELgBlyaH9p60JXAvdzWR128q+U5tU= -go.mongodb.org/mongo-driver v1.17.9/go.mod h1:LlOhpH5NUEfhxcAwG0UEkMqwYcc4JU18gtCdGudk/tQ= -go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE= -go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= +go.mongodb.org/mongo-driver/v2 v2.6.0 h1:b9sJOYrkmt4l8bY43ZenFBcPlhYIjaOfYHLtbB/5qi8= +go.mongodb.org/mongo-driver/v2 v2.6.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/detectors/gcp v1.40.0 h1:Awaf8gmW99tZTOWqkLCOl6aw1/rxAWVlHsHIZ3fT2sA= @@ -384,6 +392,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/pbm/archive/archive.go b/pbm/archive/archive.go index be6a598cc..82be8485f 100644 --- a/pbm/archive/archive.go +++ b/pbm/archive/archive.go @@ -7,8 +7,8 @@ import ( "github.com/mongodb/mongo-tools/common/archive" "github.com/mongodb/mongo-tools/common/db" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/x/bsonx/bsoncore" "golang.org/x/sync/errgroup" "github.com/percona/percona-backup-mongodb/pbm/errors" @@ -224,7 +224,8 @@ func closeChunk(w io.Writer, ns *Namespace) error { Database: ns.Database, Collection: ns.Collection, EOF: true, - CRC: ns.CRC, + // migration mongo-driver v1->v2: fix this in PBM-1682 + CRC: uint64(ns.CRC), //nolint:gosec } if ns.Type == "timeseries" { nsHeader.Collection = "system.buckets." + nsHeader.Collection diff --git a/pbm/archive/backup.go b/pbm/archive/backup.go index 3280e969a..4c4fc123f 100644 --- a/pbm/archive/backup.go +++ b/pbm/archive/backup.go @@ -10,8 +10,8 @@ import ( "strings" "sync" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "golang.org/x/sync/errgroup" "github.com/percona/percona-backup-mongodb/pbm/errors" diff --git a/pbm/archive/backup_test.go b/pbm/archive/backup_test.go index 6240f676b..91190715f 100644 --- a/pbm/archive/backup_test.go +++ b/pbm/archive/backup_test.go @@ -10,9 +10,9 @@ import ( "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/mongodb" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" ) var mClient *mongo.Client @@ -27,7 +27,7 @@ func TestMain(m *testing.M) { if err != nil { log.Fatalf("conn string error: %v", err) } - mClient, err = mongo.Connect(ctx, options.Client().ApplyURI(connStr)) + mClient, err = mongo.Connect(options.Client().ApplyURI(connStr)) if err != nil { log.Fatalf("mongo client connect error: %v", err) } diff --git a/pbm/archive/conv.go b/pbm/archive/conv.go index d3b0e17a4..fab46b86b 100644 --- a/pbm/archive/conv.go +++ b/pbm/archive/conv.go @@ -11,7 +11,7 @@ import ( mtArchive "github.com/mongodb/mongo-tools/common/archive" "github.com/pkg/errors" - "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/log" "github.com/percona/percona-backup-mongodb/pbm/storage" diff --git a/pbm/backup/backup.go b/pbm/backup/backup.go index e82b26613..a9a62e810 100644 --- a/pbm/backup/backup.go +++ b/pbm/backup/backup.go @@ -6,8 +6,8 @@ import ( "encoding/json" "time" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/config" "github.com/percona/percona-backup-mongodb/pbm/connect" @@ -125,9 +125,9 @@ func (b *Backup) Init( Status: defs.StatusStarting, Replsets: []BackupReplset{}, // the driver (mongo?) sets TS to the current wall clock if TS was 0, so have to init with 1 - LastWriteTS: primitive.Timestamp{T: 1, I: 1}, + LastWriteTS: bson.Timestamp{T: 1, I: 1}, // the driver (mongo?) sets TS to the current wall clock if TS was 0, so have to init with 1 - FirstWriteTS: primitive.Timestamp{T: 1, I: 1}, + FirstWriteTS: bson.Timestamp{T: 1, I: 1}, PBMVersion: version.Current().Version, MongoVersion: b.mongoVersion, Nomination: []BackupRsNomination{}, @@ -628,7 +628,7 @@ func (b *Backup) waitForStatus( func (b *Backup) waitForFirstLastWrite( ctx context.Context, bcpName string, -) (first, last primitive.Timestamp, err error) { +) (first, last bson.Timestamp, err error) { tk := time.NewTicker(time.Second * 1) defer tk.Stop() @@ -703,17 +703,17 @@ func (b *Backup) setClusterFirstWrite(ctx context.Context, bcpName string) error } func (b *Backup) setClusterLastWrite(ctx context.Context, bcpName string) error { - return setClusterLastWriteImpl(ctx, b.leadConn, primitive.Timestamp.Before, bcpName) + return setClusterLastWriteImpl(ctx, b.leadConn, bson.Timestamp.Before, bcpName) } func (b *Backup) setClusterLastWriteForPhysical(ctx context.Context, bcpName string) error { - return setClusterLastWriteImpl(ctx, b.leadConn, primitive.Timestamp.After, bcpName) + return setClusterLastWriteImpl(ctx, b.leadConn, bson.Timestamp.After, bcpName) } func setClusterLastWriteImpl( ctx context.Context, conn connect.Client, - cmp func(a, b primitive.Timestamp) bool, + cmp func(a, b bson.Timestamp) bool, bcpName string, ) error { var err error diff --git a/pbm/backup/backup_test.go b/pbm/backup/backup_test.go index 3f5ff5eff..dad791949 100644 --- a/pbm/backup/backup_test.go +++ b/pbm/backup/backup_test.go @@ -14,11 +14,12 @@ import ( "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/percona/percona-backup-mongodb/pbm/defs" - stds3 "github.com/percona/percona-backup-mongodb/pbm/storage/s3" "github.com/stretchr/testify/assert" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/minio" + + "github.com/percona/percona-backup-mongodb/pbm/defs" + stds3 "github.com/percona/percona-backup-mongodb/pbm/storage/s3" ) func TestMetadataEncodeDecodeWithMinio(t *testing.T) { diff --git a/pbm/backup/chunk.go b/pbm/backup/chunk.go index e928f482a..fb0b5df2c 100644 --- a/pbm/backup/chunk.go +++ b/pbm/backup/chunk.go @@ -6,7 +6,7 @@ import ( "strings" "time" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/compress" "github.com/percona/percona-backup-mongodb/pbm/errors" @@ -14,7 +14,7 @@ import ( const chunkUnixFormat = "20060102150405" -func FormatChunkName(start, end primitive.Timestamp, cmp compress.CompressionType) string { +func FormatChunkName(start, end bson.Timestamp, cmp compress.CompressionType) string { return fmt.Sprintf("%s-%s.%s-%s%s", time.Unix(int64(start.T), 0).UTC().Format(chunkUnixFormat), strconv.Itoa(int(start.I)), @@ -25,8 +25,8 @@ func FormatChunkName(start, end primitive.Timestamp, cmp compress.CompressionTyp //nolint:nonamedreturns func ParseChunkName(filename string) ( - start primitive.Timestamp, - end primitive.Timestamp, + start bson.Timestamp, + end bson.Timestamp, comp compress.CompressionType, err error, ) { @@ -59,8 +59,8 @@ func ParseChunkName(filename string) ( return } -func parseChunkTime(s string) (primitive.Timestamp, error) { - var rv primitive.Timestamp +func parseChunkTime(s string) (bson.Timestamp, error) { + var rv bson.Timestamp parts := strings.SplitN(s, "-", 2) if len(parts) != 2 || parts[0] == "" || parts[1] == "" { diff --git a/pbm/backup/delete.go b/pbm/backup/delete.go index c5c37a04d..fabdf09e8 100644 --- a/pbm/backup/delete.go +++ b/pbm/backup/delete.go @@ -4,10 +4,9 @@ import ( "context" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" "github.com/percona/percona-backup-mongodb/pbm/config" "github.com/percona/percona-backup-mongodb/pbm/connect" @@ -152,7 +151,7 @@ func CanDeleteBackup(ctx context.Context, conn connect.Client, bcp *BackupMeta) return ErrIncrementalBackup } - required, err := isRequiredForOplogSlicing(ctx, conn, bcp.LastWriteTS, primitive.Timestamp{}) + required, err := isRequiredForOplogSlicing(ctx, conn, bcp.LastWriteTS, bson.Timestamp{}) if err != nil { return errors.Wrap(err, "check pitr requirements") } @@ -284,8 +283,8 @@ func isValidBaseSnapshot(bcp *BackupMeta) bool { func isRequiredForOplogSlicing( ctx context.Context, conn connect.Client, - lw primitive.Timestamp, - baseLW primitive.Timestamp, + lw bson.Timestamp, + baseLW bson.Timestamp, ) (bool, error) { enabled, oplogOnly, err := config.IsPITREnabled(ctx, conn) if err != nil { @@ -330,7 +329,7 @@ func DeleteBackupBefore( bcpType defs.BackupType, t time.Time, ) error { - backups, err := ListDeleteBackupBefore(ctx, conn, primitive.Timestamp{T: uint32(t.Unix())}, bcpType, profile) + backups, err := ListDeleteBackupBefore(ctx, conn, bson.Timestamp{T: uint32(t.Unix())}, bcpType, profile) if err != nil { return err } @@ -355,7 +354,7 @@ func DeleteBackupBefore( func ListDeleteBackupBefore( ctx context.Context, conn connect.Client, - ts primitive.Timestamp, + ts bson.Timestamp, bcpType defs.BackupType, profile string, ) ([]BackupMeta, error) { @@ -395,10 +394,10 @@ func ListDeleteBackupBefore( func MakeCleanupInfo( ctx context.Context, conn connect.Client, - ts primitive.Timestamp, + ts bson.Timestamp, profile string, ) (CleanupInfo, error) { - backups, err := listBackupsBefore(ctx, conn, primitive.Timestamp{T: ts.T + 1}, profile) + backups, err := listBackupsBefore(ctx, conn, bson.Timestamp{T: ts.T + 1}, profile) if err != nil { return CleanupInfo{}, errors.Wrap(err, "list backups before") } @@ -532,7 +531,7 @@ func MakeCleanupInfo( func listBackupsBefore( ctx context.Context, conn connect.Client, - ts primitive.Timestamp, + ts bson.Timestamp, profile string, ) ([]BackupMeta, error) { f := bson.D{ @@ -561,7 +560,7 @@ func listBackupsBefore( } // listChunksBefore returns oplog chunks that start before `ts`. -func listChunksBefore(ctx context.Context, conn connect.Client, ts primitive.Timestamp) ([]oplog.OplogChunk, error) { +func listChunksBefore(ctx context.Context, conn connect.Client, ts bson.Timestamp) ([]oplog.OplogChunk, error) { f := bson.D{{"start_ts", bson.M{"$lt": ts}}} o := options.Find().SetSort(bson.D{{"start_ts", 1}}) cur, err := conn.PITRChunksCollection().Find(ctx, f, o) diff --git a/pbm/backup/delete_test.go b/pbm/backup/delete_test.go index 1f4ef7ed1..283fcf215 100644 --- a/pbm/backup/delete_test.go +++ b/pbm/backup/delete_test.go @@ -7,16 +7,16 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.mongodb.org/mongo-driver/v2/bson" + "github.com/percona/percona-backup-mongodb/pbm/compress" "github.com/percona/percona-backup-mongodb/pbm/config" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/defs" "github.com/percona/percona-backup-mongodb/pbm/oplog" "github.com/percona/percona-backup-mongodb/pbm/storage" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" ) type chunk struct { @@ -151,10 +151,10 @@ func TestIsRequiredForOplogSlicing(t *testing.T) { insertTestBackupsStorage(t, TestEnv, TestEnv.PbmStorage, tt.backups) insertTestChunks(t, TestEnv, tt.chunks) - lwtBson := primitive.Timestamp{T: uint32(tt.lwt.Unix())} - baseLWTBson := primitive.Timestamp{T: uint32(tt.baseLWT.Unix())} + lwtBson := bson.Timestamp{T: uint32(tt.lwt.Unix())} + baseLWTBson := bson.Timestamp{T: uint32(tt.baseLWT.Unix())} if baseLWTBson.IsZero() { - baseLWTBson = primitive.Timestamp{} + baseLWTBson = bson.Timestamp{} } actual, err := isRequiredForOplogSlicing(t.Context(), TestEnv.Client, lwtBson, baseLWTBson) @@ -259,7 +259,7 @@ func TestListDeleteBackups(t *testing.T) { storages := stgsFromTestBackups(t, tt.backups) expected := insertTestBackups(t, TestEnv, storages, tt.backups) - before := primitive.Timestamp{T: uint32(tt.before.Unix())} + before := bson.Timestamp{T: uint32(tt.before.Unix())} for profile := range tt.backups { bcps, err := ListDeleteBackupBefore(t.Context(), TestEnv.Client, before, tt.bcpType, profile) @@ -405,7 +405,7 @@ func TestMakeCleanupInfo(t *testing.T) { storages := stgsFromTestBackups(t, tt.backups) expectedChunks := insertTestChunks(t, TestEnv, tt.chunks) expectedBackupNames := insertTestBackups(t, TestEnv, storages, tt.backups) - before := primitive.Timestamp{T: uint32(tt.before.Unix())} + before := bson.Timestamp{T: uint32(tt.before.Unix())} for profile := range tt.backups { info, err := MakeCleanupInfo(t.Context(), TestEnv.Client, before, profile) @@ -463,7 +463,7 @@ func TestListChunksBefore(t *testing.T) { t.Run(tt.name, func(t *testing.T) { TestEnv.Reset(t) - before := primitive.Timestamp{T: uint32(tt.before.Unix())} + before := bson.Timestamp{T: uint32(tt.before.Unix())} expected := insertTestChunks(t, TestEnv, tt.chunks) chunks, err := listChunksBefore(t.Context(), TestEnv.Client, before) @@ -560,7 +560,7 @@ func TestListBackupsBefore(t *testing.T) { storages := stgsFromTestBackups(t, tt.backups) expected := insertTestBackups(t, TestEnv, storages, tt.backups) - before := primitive.Timestamp{T: uint32(tt.before.Unix())} + before := bson.Timestamp{T: uint32(tt.before.Unix())} for profile := range tt.backups { bcps, err := listBackupsBefore(t.Context(), TestEnv.Client, before, profile) @@ -691,8 +691,8 @@ func insertTestChunks(t *testing.T, env *TestEnvironment, chunks []chunk) []oplo func insertTestChunkMeta(t *testing.T, env *TestEnvironment, c chunk) oplog.OplogChunk { t.Helper() - fromBson := primitive.Timestamp{T: uint32(c.From.Unix())} - toBson := primitive.Timestamp{T: uint32(c.To.Unix())} + fromBson := bson.Timestamp{T: uint32(c.From.Unix())} + toBson := bson.Timestamp{T: uint32(c.To.Unix())} compression := compress.CompressionTypeS2 filename := oplog.FormatChunkFilepath(env.Brief.SetName, fromBson, toBson, compression) diff --git a/pbm/backup/logical.go b/pbm/backup/logical.go index dddb84031..87d716d34 100644 --- a/pbm/backup/logical.go +++ b/pbm/backup/logical.go @@ -8,10 +8,9 @@ import ( "sync" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" "golang.org/x/sync/errgroup" "github.com/percona/percona-backup-mongodb/pbm/archive" @@ -95,7 +94,7 @@ func (b *Backup) doLogical( b.leadConn.MongoOptions().WriteConcern, b.SlicerInterval(), rsMeta.FirstWriteTS, - func(ctx context.Context, w io.WriterTo, from, till primitive.Timestamp) (int64, error) { + func(ctx context.Context, w io.WriterTo, from, till bson.Timestamp) (int64, error) { filename := rsMeta.OplogName + "/" + FormatChunkName(from, till, bcp.Compression) bytesPerSecond, err := getOplogBytesPerSecond(ctx, b.nodeConn) @@ -278,8 +277,8 @@ func dropTMPcoll(ctx context.Context, uri string) error { return nil } -func waitForWrite(ctx context.Context, m *mongo.Client, ts primitive.Timestamp) error { - var lw primitive.Timestamp +func waitForWrite(ctx context.Context, m *mongo.Client, ts bson.Timestamp) error { + var lw bson.Timestamp var err error for i := 0; i < 21; i++ { @@ -298,7 +297,7 @@ func waitForWrite(ctx context.Context, m *mongo.Client, ts primitive.Timestamp) } //nolint:nonamedreturns -func copyUsersNRolles(ctx context.Context, uri string, nss []string) (lastWrite primitive.Timestamp, err error) { +func copyUsersNRolles(ctx context.Context, uri string, nss []string) (lastWrite bson.Timestamp, err error) { cn, err := connect.MongoConnect(ctx, uri) if err != nil { return lastWrite, errors.Wrap(err, "connect to primary") @@ -536,16 +535,16 @@ func getOplogBytesPerSecond(ctx context.Context, m *mongo.Client) (float64, erro } // oplogTimestamp returns the timestamp of the first (sort=1) or last (sort=-1) document in the oplog. -func oplogTimestamp(ctx context.Context, coll *mongo.Collection, sort int) (primitive.Timestamp, error) { +func oplogTimestamp(ctx context.Context, coll *mongo.Collection, sort int) (bson.Timestamp, error) { var doc bson.M err := coll.FindOne(ctx, bson.D{}, options.FindOne().SetSort(bson.D{{Key: "$natural", Value: sort}})).Decode(&doc) if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "query oplog timestamp") + return bson.Timestamp{}, errors.Wrap(err, "query oplog timestamp") } - ts, ok := doc["ts"].(primitive.Timestamp) + ts, ok := doc["ts"].(bson.Timestamp) if !ok { - return primitive.Timestamp{}, errors.New("missing or invalid 'ts' field") + return bson.Timestamp{}, errors.New("missing or invalid 'ts' field") } return ts, nil diff --git a/pbm/backup/logical_test.go b/pbm/backup/logical_test.go index 4fb4e9966..cc086f6a0 100644 --- a/pbm/backup/logical_test.go +++ b/pbm/backup/logical_test.go @@ -3,7 +3,7 @@ package backup import ( "testing" - "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/util" ) diff --git a/pbm/backup/main_test.go b/pbm/backup/main_test.go index e23310366..28e03671d 100644 --- a/pbm/backup/main_test.go +++ b/pbm/backup/main_test.go @@ -12,8 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/mongodb" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/compress" "github.com/percona/percona-backup-mongodb/pbm/config" @@ -151,7 +150,7 @@ func (tenv *TestEnvironment) resetMongo(ctx context.Context) error { // drop PBM collections db := mongo.Database(defs.DB) - pbmColFilter := bson.D{{Key: "name", Value: primitive.Regex{Pattern: "^pbm"}}} + pbmColFilter := bson.D{{Key: "name", Value: bson.Regex{Pattern: "^pbm"}}} collections, err := db.ListCollectionNames(ctx, pbmColFilter) if err != nil { return err @@ -239,7 +238,7 @@ func insertTestBcpMeta(t *testing.T, env *TestEnvironment, stg Storage, b bcp) B meta := BackupMeta{ Type: b.BcpType, - OPID: ctrl.OPID(primitive.NilObjectID).String(), + OPID: ctrl.OPID(bson.NilObjectID).String(), Name: b.Name, Namespaces: make([]string, 0), Compression: compress.CompressionTypeS2, @@ -247,13 +246,13 @@ func insertTestBcpMeta(t *testing.T, env *TestEnvironment, stg Storage, b bcp) B StartTS: time.Now().Unix(), Status: defs.StatusDone, Replsets: []BackupReplset{}, - LastWriteTS: primitive.Timestamp{T: uint32(b.LWT.Unix())}, - FirstWriteTS: primitive.Timestamp{T: uint32(firstWrite.Unix())}, + LastWriteTS: bson.Timestamp{T: uint32(b.LWT.Unix())}, + FirstWriteTS: bson.Timestamp{T: uint32(firstWrite.Unix())}, PBMVersion: version.Current().Version, MongoVersion: env.Brief.Version.String(), Nomination: []BackupRsNomination{}, BalancerStatus: topo.BalancerModeOff, - Hb: primitive.Timestamp{T: uint32(b.LWT.Unix())}, + Hb: bson.Timestamp{T: uint32(b.LWT.Unix())}, } _, err := env.Client.BcpCollection().InsertOne(t.Context(), meta) diff --git a/pbm/backup/physical.go b/pbm/backup/physical.go index 0ab9deeff..1e06cd6e8 100644 --- a/pbm/backup/physical.go +++ b/pbm/backup/physical.go @@ -12,11 +12,9 @@ import ( "time" "github.com/google/uuid" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/bsontype" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/x/bsonx/bsoncore" "github.com/percona/percona-backup-mongodb/pbm/compress" "github.com/percona/percona-backup-mongodb/pbm/ctrl" @@ -35,16 +33,16 @@ const ( ) type Meta struct { - ID UUID `bson:"backupId"` - DBpath string `bson:"dbpath"` - OplogStart BCoplogTS `bson:"oplogStart"` - OplogEnd BCoplogTS `bson:"oplogEnd"` - CheckpointTS primitive.Timestamp `bson:"checkpointTimestamp"` + ID UUID `bson:"backupId"` + DBpath string `bson:"dbpath"` + OplogStart BCoplogTS `bson:"oplogStart"` + OplogEnd BCoplogTS `bson:"oplogEnd"` + CheckpointTS bson.Timestamp `bson:"checkpointTimestamp"` } type BCoplogTS struct { - TS primitive.Timestamp `bson:"ts"` - T int64 `bson:"t"` + TS bson.Timestamp `bson:"ts"` + T int64 `bson:"t"` } // see https://www.percona.com/blog/2021/06/07/experimental-feature-backupcursorextend-in-percona-server-for-mongodb/ @@ -187,7 +185,7 @@ func (bc *BackupCursor) Data(ctx context.Context) (_ *BackupCursorData, err erro return &BackupCursorData{m, files}, nil } -func (bc *BackupCursor) Journals(upto primitive.Timestamp) ([]File, error) { +func (bc *BackupCursor) Journals(upto bson.Timestamp) ([]File, error) { ctx := context.Background() cur, err := bc.conn.Database("admin").Aggregate(ctx, mongo.Pipeline{ @@ -618,13 +616,13 @@ func getStorageBSON(dbpath string) (*File, error) { type UUID struct{ uuid.UUID } // MarshalBSONValue implements the bson.ValueMarshaler interface. -func (id UUID) MarshalBSONValue() (bsontype.Type, []byte, error) { - return bson.TypeBinary, bsoncore.AppendBinary(nil, 4, id.UUID[:]), nil +func (id UUID) MarshalBSONValue() (byte, []byte, error) { + return byte(bson.TypeBinary), bsoncore.AppendBinary(nil, 4, id.UUID[:]), nil } // UnmarshalBSONValue implements the bson.ValueUnmarshaler interface. -func (id *UUID) UnmarshalBSONValue(t bsontype.Type, raw []byte) error { - if t != bson.TypeBinary { +func (id *UUID) UnmarshalBSONValue(t byte, raw []byte) error { + if t != byte(bson.TypeBinary) { return errors.New("invalid format on unmarshal bson value") } diff --git a/pbm/backup/physical_test.go b/pbm/backup/physical_test.go index 93d7075e2..c7ab97572 100644 --- a/pbm/backup/physical_test.go +++ b/pbm/backup/physical_test.go @@ -4,8 +4,8 @@ import ( "context" "testing" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/log" ) diff --git a/pbm/backup/query.go b/pbm/backup/query.go index 3f64553f1..01046e0ab 100644 --- a/pbm/backup/query.go +++ b/pbm/backup/query.go @@ -4,10 +4,9 @@ import ( "context" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/defs" @@ -164,7 +163,7 @@ func SetSrcBackup(ctx context.Context, conn connect.Client, bcpName, srcName str return err } -func SetFirstWrite(ctx context.Context, conn connect.Client, bcpName string, first primitive.Timestamp) error { +func SetFirstWrite(ctx context.Context, conn connect.Client, bcpName string, first bson.Timestamp) error { _, err := conn.BcpCollection().UpdateOne( ctx, bson.D{{"name", bcpName}}, @@ -176,7 +175,7 @@ func SetFirstWrite(ctx context.Context, conn connect.Client, bcpName string, fir return err } -func SetLastWrite(ctx context.Context, conn connect.Client, bcpName string, last primitive.Timestamp) error { +func SetLastWrite(ctx context.Context, conn connect.Client, bcpName string, last bson.Timestamp) error { _, err := conn.BcpCollection().UpdateOne( ctx, bson.D{{"name", bcpName}}, @@ -265,7 +264,7 @@ func SetBackupSizeForRS( return err } -func SetRSLastWrite(conn connect.Client, bcpName, rsName string, ts primitive.Timestamp) error { +func SetRSLastWrite(conn connect.Client, bcpName, rsName string, ts bson.Timestamp) error { _, err := conn.BcpCollection().UpdateOne( context.Background(), bson.D{{"name", bcpName}, {"replsets.name", rsName}}, @@ -284,7 +283,7 @@ func LastIncrementalBackup(ctx context.Context, conn connect.Client) (*BackupMet // GetLastBackup returns last successfully finished backup (non-selective and non-external) // or nil if there is no such backup yet. If ts isn't nil it will // search for the most recent backup that finished before specified timestamp -func GetLastBackup(ctx context.Context, conn connect.Client, before *primitive.Timestamp) (*BackupMeta, error) { +func GetLastBackup(ctx context.Context, conn connect.Client, before *bson.Timestamp) (*BackupMeta, error) { return getRecentBackup(ctx, conn, nil, before, -1, bson.D{ {"nss", nil}, {"type", bson.M{"$ne": defs.ExternalBackup}}, @@ -292,7 +291,7 @@ func GetLastBackup(ctx context.Context, conn connect.Client, before *primitive.T }) } -func GetFirstBackup(ctx context.Context, conn connect.Client, after *primitive.Timestamp) (*BackupMeta, error) { +func GetFirstBackup(ctx context.Context, conn connect.Client, after *bson.Timestamp) (*BackupMeta, error) { return getRecentBackup(ctx, conn, after, nil, 1, bson.D{ {"nss", nil}, {"type", bson.M{"$ne": defs.ExternalBackup}}, @@ -304,7 +303,7 @@ func getRecentBackup( ctx context.Context, conn connect.Client, after, - before *primitive.Timestamp, + before *bson.Timestamp, sort int, opts bson.D, ) (*BackupMeta, error) { @@ -337,17 +336,17 @@ func getRecentBackup( func FindBaseSnapshotLWAfter( ctx context.Context, conn connect.Client, - lw primitive.Timestamp, -) (primitive.Timestamp, error) { + lw bson.Timestamp, +) (bson.Timestamp, error) { return findBaseSnapshotLWImpl(ctx, conn, bson.M{"$gt": lw}, 1) } func FindBaseSnapshotLWBefore( ctx context.Context, conn connect.Client, - lw primitive.Timestamp, - exclude primitive.Timestamp, -) (primitive.Timestamp, error) { + lw bson.Timestamp, + exclude bson.Timestamp, +) (bson.Timestamp, error) { return findBaseSnapshotLWImpl(ctx, conn, bson.M{"$lt": lw, "$ne": exclude}, -1) } @@ -356,7 +355,7 @@ func findBaseSnapshotLWImpl( conn connect.Client, lwCond bson.M, sort int, -) (primitive.Timestamp, error) { +) (bson.Timestamp, error) { f := bson.D{ {"nss", nil}, {"type", bson.M{"$ne": defs.ExternalBackup}}, @@ -372,7 +371,7 @@ func findBaseSnapshotLWImpl( if errors.Is(err, mongo.ErrNoDocuments) { err = nil } - return primitive.Timestamp{}, errors.Wrap(err, "query") + return bson.Timestamp{}, errors.Wrap(err, "query") } bcp := &BackupMeta{} @@ -414,7 +413,7 @@ func BackupsList( func BackupsDoneList( ctx context.Context, conn connect.Client, - after *primitive.Timestamp, + after *bson.Timestamp, limit int64, order int, ) ([]BackupMeta, error) { diff --git a/pbm/backup/slicer.go b/pbm/backup/slicer.go index 0ae56e495..0c11a922a 100644 --- a/pbm/backup/slicer.go +++ b/pbm/backup/slicer.go @@ -7,25 +7,25 @@ import ( "io" "time" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/writeconcern" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/writeconcern" "github.com/percona/percona-backup-mongodb/pbm/log" "github.com/percona/percona-backup-mongodb/pbm/oplog" "github.com/percona/percona-backup-mongodb/pbm/topo" ) -type uploadChunkFunc func(ctx context.Context, w io.WriterTo, from, till primitive.Timestamp) (int64, error) +type uploadChunkFunc func(ctx context.Context, w io.WriterTo, from, till bson.Timestamp) (int64, error) -type stopSlicerFunc func() (primitive.Timestamp, int64, error) +type stopSlicerFunc func() (bson.Timestamp, int64, error) func startOplogSlicer( ctx context.Context, m *mongo.Client, writeConcern *writeconcern.WriteConcern, interval time.Duration, - startOpTime primitive.Timestamp, + startOpTime bson.Timestamp, upload uploadChunkFunc, ) stopSlicerFunc { l := log.LogEventFromContext(ctx) @@ -99,7 +99,7 @@ func startOplogSlicer( } }() - return func() (primitive.Timestamp, int64, error) { + return func() (bson.Timestamp, int64, error) { select { case <-stoppedC: // already closed diff --git a/pbm/backup/types.go b/pbm/backup/types.go index 4eb342e72..46348df2b 100644 --- a/pbm/backup/types.go +++ b/pbm/backup/types.go @@ -6,8 +6,7 @@ import ( "os" "path/filepath" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/archive" "github.com/percona/percona-backup-mongodb/pbm/compress" @@ -50,9 +49,9 @@ type BackupMeta struct { FCV string `bson:"fcv" json:"fcv"` StartTS int64 `bson:"start_ts" json:"start_ts"` LastTransitionTS int64 `bson:"last_transition_ts" json:"last_transition_ts"` - FirstWriteTS primitive.Timestamp `bson:"first_write_ts" json:"first_write_ts"` - LastWriteTS primitive.Timestamp `bson:"last_write_ts" json:"last_write_ts"` - Hb primitive.Timestamp `bson:"hb" json:"hb"` + FirstWriteTS bson.Timestamp `bson:"first_write_ts" json:"first_write_ts"` + LastWriteTS bson.Timestamp `bson:"last_write_ts" json:"last_write_ts"` + Hb bson.Timestamp `bson:"hb" json:"hb"` Status defs.Status `bson:"status" json:"status"` Conditions []Condition `bson:"conditions" json:"conditions"` Nomination []BackupRsNomination `bson:"n" json:"n"` @@ -113,23 +112,23 @@ type BackupReplset struct { Name string `bson:"name" json:"name"` // Journal is not used. left for backward compatibility - Journal []File `bson:"journal,omitempty" json:"journal,omitempty"` - Files []File `bson:"files,omitempty" json:"files,omitempty"` - DumpName string `bson:"dump_name,omitempty" json:"backup_name,omitempty"` - OplogName string `bson:"oplog_name,omitempty" json:"oplog_name,omitempty"` - StartTS int64 `bson:"start_ts" json:"start_ts"` - Status defs.Status `bson:"status" json:"status"` - Size int64 `bson:"size" json:"size"` - SizeUncompressed int64 `bson:"size_uncompressed" json:"size_uncompressed"` - IsConfigSvr *bool `bson:"iscs,omitempty" json:"iscs,omitempty"` - IsConfigShard *bool `bson:"configshard,omitempty" json:"configshard,omitempty"` - LastTransitionTS int64 `bson:"last_transition_ts" json:"last_transition_ts"` - FirstWriteTS primitive.Timestamp `bson:"first_write_ts" json:"first_write_ts"` - LastWriteTS primitive.Timestamp `bson:"last_write_ts" json:"last_write_ts"` - Node string `bson:"node" json:"node"` // node that performed backup - Error string `bson:"error,omitempty" json:"error,omitempty"` - Conditions []Condition `bson:"conditions" json:"conditions"` - MongodOpts *topo.MongodOpts `bson:"mongod_opts,omitempty" json:"mongod_opts,omitempty"` + Journal []File `bson:"journal,omitempty" json:"journal,omitempty"` + Files []File `bson:"files,omitempty" json:"files,omitempty"` + DumpName string `bson:"dump_name,omitempty" json:"backup_name,omitempty"` + OplogName string `bson:"oplog_name,omitempty" json:"oplog_name,omitempty"` + StartTS int64 `bson:"start_ts" json:"start_ts"` + Status defs.Status `bson:"status" json:"status"` + Size int64 `bson:"size" json:"size"` + SizeUncompressed int64 `bson:"size_uncompressed" json:"size_uncompressed"` + IsConfigSvr *bool `bson:"iscs,omitempty" json:"iscs,omitempty"` + IsConfigShard *bool `bson:"configshard,omitempty" json:"configshard,omitempty"` + LastTransitionTS int64 `bson:"last_transition_ts" json:"last_transition_ts"` + FirstWriteTS bson.Timestamp `bson:"first_write_ts" json:"first_write_ts"` + LastWriteTS bson.Timestamp `bson:"last_write_ts" json:"last_write_ts"` + Node string `bson:"node" json:"node"` // node that performed backup + Error string `bson:"error,omitempty" json:"error,omitempty"` + Conditions []Condition `bson:"conditions" json:"conditions"` + MongodOpts *topo.MongodOpts `bson:"mongod_opts,omitempty" json:"mongod_opts,omitempty"` // required for external backup (PBM-1252) PBMVersion string `bson:"pbm_version,omitempty" json:"pbm_version,omitempty"` diff --git a/pbm/config/config.go b/pbm/config/config.go index 5347f9df7..f647cf136 100644 --- a/pbm/config/config.go +++ b/pbm/config/config.go @@ -11,11 +11,10 @@ import ( "strings" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" - "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" + "go.mongodb.org/mongo-driver/v2/x/bsonx/bsoncore" "gopkg.in/yaml.v2" "github.com/percona/percona-backup-mongodb/pbm/compress" @@ -50,7 +49,7 @@ func keys(t reflect.Type) confMap { name := strings.TrimSpace(strings.Split(t.Field(i).Tag.Get("bson"), ",")[0]) typ := t.Field(i).Type - if typ.Kind() == reflect.Ptr { + if typ.Kind() == reflect.Pointer { typ = typ.Elem() } if typ.Kind() == reflect.Struct { @@ -80,7 +79,7 @@ type Config struct { Backup *BackupConf `bson:"backup,omitempty" json:"backup,omitempty" yaml:"backup,omitempty"` Restore *RestoreConf `bson:"restore,omitempty" json:"restore,omitempty" yaml:"restore,omitempty"` - Epoch primitive.Timestamp `bson:"epoch" json:"-" yaml:"-"` + Epoch bson.Timestamp `bson:"epoch" json:"-" yaml:"-"` } func Parse(r io.Reader) (*Config, error) { @@ -802,10 +801,10 @@ func IsPITREnabled(ctx context.Context, m connect.Client) (bool, bool, error) { return cfg.PITR.Enabled, cfg.PITR.OplogOnly, nil } -type Epoch primitive.Timestamp +type Epoch bson.Timestamp -func (e Epoch) TS() primitive.Timestamp { - return primitive.Timestamp(e) +func (e Epoch) TS() bson.Timestamp { + return bson.Timestamp(e) } func GetEpoch(ctx context.Context, m connect.Client) (Epoch, error) { diff --git a/pbm/config/config_test.go b/pbm/config/config_test.go index f31748a1b..090f2e55d 100644 --- a/pbm/config/config_test.go +++ b/pbm/config/config_test.go @@ -14,9 +14,9 @@ import ( "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/mongodb" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" - "go.mongodb.org/mongo-driver/mongo/readpref" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" + "go.mongodb.org/mongo-driver/v2/mongo/readpref" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/storage" @@ -316,7 +316,7 @@ func TestMain(m *testing.M) { log.Fatalf("conn string error: %v", err) } connStr += "&directConnection=true" - mClient, err := mongo.Connect(ctx, options.Client().ApplyURI(connStr)) + mClient, err := mongo.Connect(options.Client().ApplyURI(connStr)) if err != nil { log.Fatalf("mongo client connect error: %v", err) } diff --git a/pbm/config/profile.go b/pbm/config/profile.go index 1cc8dbe8e..4d927205d 100644 --- a/pbm/config/profile.go +++ b/pbm/config/profile.go @@ -4,9 +4,9 @@ import ( "context" "os" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/errors" diff --git a/pbm/config/util.go b/pbm/config/util.go index 219477a37..1fd1a4f8e 100644 --- a/pbm/config/util.go +++ b/pbm/config/util.go @@ -3,7 +3,7 @@ package config import ( "context" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/errors" diff --git a/pbm/connect/connect.go b/pbm/connect/connect.go index 40afe264f..cc32d6b6c 100644 --- a/pbm/connect/connect.go +++ b/pbm/connect/connect.go @@ -6,12 +6,12 @@ import ( "strings" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" - "go.mongodb.org/mongo-driver/mongo/readconcern" - "go.mongodb.org/mongo-driver/mongo/readpref" - "go.mongodb.org/mongo-driver/mongo/writeconcern" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" + "go.mongodb.org/mongo-driver/v2/mongo/readconcern" + "go.mongodb.org/mongo-driver/v2/mongo/readpref" + "go.mongodb.org/mongo-driver/v2/mongo/writeconcern" "github.com/percona/percona-backup-mongodb/pbm/defs" "github.com/percona/percona-backup-mongodb/pbm/errors" @@ -150,7 +150,7 @@ func MongoConnectWithOpts(ctx context.Context, } } - conn, err := mongo.Connect(ctx, mopts) + conn, err := mongo.Connect(mopts) if err != nil { return nil, nil, errors.Wrap(err, "connect") } @@ -307,7 +307,11 @@ func (l *clientImpl) ConfigDatabase() *mongo.Database { return l.client.Database("config") } -func (l *clientImpl) AdminCommand(ctx context.Context, cmd bson.D, opts ...*options.RunCmdOptions) *mongo.SingleResult { +func (l *clientImpl) AdminCommand( + ctx context.Context, + cmd bson.D, + opts ...options.Lister[options.RunCmdOptions], +) *mongo.SingleResult { cmd = l.applyOptonsFromConnString(cmd) return l.client.Database(defs.DB).RunCommand(ctx, cmd, opts...) } @@ -364,8 +368,11 @@ func (l *clientImpl) applyOptonsFromConnString(cmd bson.D) bson.D { cmdName := cmd[0].Key switch cmdName { case "create": - if l.options.WriteConcern != nil { - cmd = append(cmd, bson.E{"writeConcern", l.options.WriteConcern}) + if wc := l.options.WriteConcern; wc != nil && wc.W != nil { + cmd = append(cmd, bson.E{ + Key: "writeConcern", + Value: bson.D{{Key: "w", Value: wc.W}}, + }) } default: // do nothing for all other commands: @@ -387,7 +394,7 @@ type Client interface { MongoOptions() *options.ClientOptions ConfigDatabase() *mongo.Database - AdminCommand(ctx context.Context, cmd bson.D, opts ...*options.RunCmdOptions) *mongo.SingleResult + AdminCommand(ctx context.Context, cmd bson.D, opts ...options.Lister[options.RunCmdOptions]) *mongo.SingleResult LogCollection() *mongo.Collection ConfigCollection() *mongo.Collection diff --git a/pbm/connect/todo.go b/pbm/connect/todo.go index 988c05bfa..fb89707b6 100644 --- a/pbm/connect/todo.go +++ b/pbm/connect/todo.go @@ -3,9 +3,8 @@ package connect import ( "context" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/defs" "github.com/percona/percona-backup-mongodb/pbm/errors" @@ -21,8 +20,8 @@ type nodeInfo struct { ConfigSvr int `bson:"configsvr,omitempty"` ConfigServerState *struct { OpTime *struct { - TS primitive.Timestamp `bson:"ts" json:"ts"` - Term int64 `bson:"t" json:"t"` + TS bson.Timestamp `bson:"ts" json:"ts"` + Term int64 `bson:"t" json:"t"` } `bson:"opTime"` } `bson:"$configServerState,omitempty"` Opts *mongodOpts `bson:"-"` diff --git a/pbm/ctrl/cmd.go b/pbm/ctrl/cmd.go index c85f0c632..e7797f8d0 100644 --- a/pbm/ctrl/cmd.go +++ b/pbm/ctrl/cmd.go @@ -5,7 +5,7 @@ import ( "fmt" "strconv" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/compress" "github.com/percona/percona-backup-mongodb/pbm/config" @@ -60,24 +60,24 @@ func (c Command) String() string { } } -type OPID primitive.ObjectID +type OPID bson.ObjectID func ParseOPID(s string) (OPID, error) { - o, err := primitive.ObjectIDFromHex(s) + o, err := bson.ObjectIDFromHex(s) if err != nil { - return OPID(primitive.NilObjectID), err + return OPID(bson.NilObjectID), err } return OPID(o), nil } -var NilOPID = OPID(primitive.NilObjectID) +var NilOPID = OPID(bson.NilObjectID) func (o OPID) String() string { - return primitive.ObjectID(o).Hex() + return bson.ObjectID(o).Hex() } -func (o OPID) Obj() primitive.ObjectID { - return primitive.ObjectID(o) +func (o OPID) Obj() bson.ObjectID { + return bson.ObjectID(o) } type Cmd struct { @@ -165,12 +165,12 @@ type RestoreCmd struct { NumInsertionWorkers *int32 `bson:"numInsertionWorkers,omitempty"` IndexCommitQuorum config.IndexCommitQuorum `bson:"indexCommitQuorum,omitempty"` - OplogTS primitive.Timestamp `bson:"oplogTS,omitempty"` + OplogTS bson.Timestamp `bson:"oplogTS,omitempty"` - External bool `bson:"external"` - ExtConf topo.ExternOpts `bson:"extConf"` - ExtTS primitive.Timestamp `bson:"extTS"` - Exit bool `bson:"exit"` + External bool `bson:"external"` + ExtConf topo.ExternOpts `bson:"extConf"` + ExtTS bson.Timestamp `bson:"extTS"` + Exit bool `bson:"exit"` } func (r RestoreCmd) String() string { @@ -195,10 +195,10 @@ func (r RestoreCmd) String() string { } type ReplayCmd struct { - Name string `bson:"name"` - Start primitive.Timestamp `bson:"start,omitempty"` - End primitive.Timestamp `bson:"end,omitempty"` - RSMap map[string]string `bson:"rsMap,omitempty"` + Name string `bson:"name"` + Start bson.Timestamp `bson:"start,omitempty"` + End bson.Timestamp `bson:"end,omitempty"` + RSMap map[string]string `bson:"rsMap,omitempty"` } func (c ReplayCmd) String() string { @@ -217,8 +217,8 @@ type DeletePITRCmd struct { } type CleanupCmd struct { - OlderThan primitive.Timestamp `bson:"olderThan"` - Profile string `bson:"profile"` + OlderThan bson.Timestamp `bson:"olderThan"` + Profile string `bson:"profile"` } func (d DeleteBackupCmd) String() string { diff --git a/pbm/ctrl/recv.go b/pbm/ctrl/recv.go index fed8f034b..841978436 100644 --- a/pbm/ctrl/recv.go +++ b/pbm/ctrl/recv.go @@ -4,7 +4,7 @@ import ( "context" "time" - "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/errors" diff --git a/pbm/ctrl/recv_test.go b/pbm/ctrl/recv_test.go index b889ccd92..61cf1b6d5 100644 --- a/pbm/ctrl/recv_test.go +++ b/pbm/ctrl/recv_test.go @@ -10,10 +10,9 @@ import ( "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/mongodb" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" "github.com/percona/percona-backup-mongodb/pbm/connect" ) @@ -33,7 +32,7 @@ func TestMain(m *testing.M) { if err != nil { log.Fatalf("conn string error: %v", err) } - mClient, err = mongo.Connect(ctx, options.Client().ApplyURI(connStr)) + mClient, err = mongo.Connect(options.Client().ApplyURI(connStr)) if err != nil { log.Fatalf("mongo client connect error: %v", err) } @@ -102,7 +101,7 @@ func TestListenCmd(t *testing.T) { } for _, e := range commands { - doc := bson.D{{"_id", primitive.NewObjectID()}, {"cmd", e.cmd}, {"ts", e.ts}} + doc := bson.D{{"_id", bson.NewObjectID()}, {"cmd", e.cmd}, {"ts", e.ts}} if _, err := coll.InsertOne(ctx, doc); err != nil { t.Fatalf("insert %s@%d: %v", e.cmd, e.ts, err) } diff --git a/pbm/ctrl/send.go b/pbm/ctrl/send.go index e368ba25c..087d65612 100644 --- a/pbm/ctrl/send.go +++ b/pbm/ctrl/send.go @@ -4,7 +4,7 @@ import ( "context" "time" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/config" "github.com/percona/percona-backup-mongodb/pbm/connect" @@ -25,7 +25,7 @@ func SendDeleteBackupByName(ctx context.Context, m connect.Client, name string) func SendDeleteBackupBefore( ctx context.Context, m connect.Client, - before primitive.Timestamp, + before bson.Timestamp, type_ defs.BackupType, profile string, ) (OPID, error) { @@ -43,7 +43,7 @@ func SendDeleteBackupBefore( func SendDeleteOplogRangeBefore( ctx context.Context, m connect.Client, - before primitive.Timestamp, + before bson.Timestamp, ) (OPID, error) { cmd := Cmd{ Cmd: CmdDeletePITR, @@ -57,7 +57,7 @@ func SendDeleteOplogRangeBefore( func SendCleanup( ctx context.Context, m connect.Client, - before primitive.Timestamp, + before bson.Timestamp, profile string, ) (OPID, error) { cmd := Cmd{ @@ -120,7 +120,7 @@ func sendCommand(ctx context.Context, m connect.Client, cmd Cmd) (OPID, error) { return NilOPID, err } - opid, ok := res.InsertedID.(primitive.ObjectID) + opid, ok := res.InsertedID.(bson.ObjectID) if !ok { return NilOPID, errors.New("unexpected opid type") } diff --git a/pbm/lock/lock.go b/pbm/lock/lock.go index 6cdadafb9..c2914ce72 100644 --- a/pbm/lock/lock.go +++ b/pbm/lock/lock.go @@ -4,9 +4,8 @@ import ( "context" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/ctrl" @@ -24,12 +23,12 @@ type LockHeader struct { OPID string `bson:"opid,omitempty" json:"opid,omitempty"` // should be a pointer so mongo find with empty epoch would work // otherwise it always set it at least to "epoch":{"$timestamp":{"t":0,"i":0}} - Epoch *primitive.Timestamp `bson:"epoch,omitempty" json:"epoch,omitempty"` + Epoch *bson.Timestamp `bson:"epoch,omitempty" json:"epoch,omitempty"` } type LockData struct { LockHeader `bson:",inline"` - Heartbeat primitive.Timestamp `bson:"hb"` // separated in order the lock can be searchable by the header + Heartbeat bson.Timestamp `bson:"hb"` // separated in order the lock can be searchable by the header } // Lock is a lock for the PBM operation (e.g. backup, restore) @@ -126,7 +125,7 @@ func (l *Lock) log(ctx context.Context) error { // PITR slicing technically speaking is not an OP but // long standing process. It souldn't be logged. Moreover // having no opid it would block all subsequent PITR events. - if l.LockHeader.Type == ctrl.CmdPITR { + if l.Type == ctrl.CmdPITR { return nil } diff --git a/pbm/log/discard.go b/pbm/log/discard.go index 3119efb1b..489397926 100644 --- a/pbm/log/discard.go +++ b/pbm/log/discard.go @@ -3,12 +3,12 @@ package log import ( "context" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" ) type discardLoggerImpl struct{} -func (l discardLoggerImpl) NewEvent(typ, name, opid string, epoch primitive.Timestamp) LogEvent { +func (l discardLoggerImpl) NewEvent(typ, name, opid string, epoch bson.Timestamp) LogEvent { return l.NewDefaultEvent() } @@ -35,19 +35,19 @@ func (discardLoggerImpl) Write([]byte) (int, error) { func (discardLoggerImpl) Printf(msg string, args ...any) { } -func (discardLoggerImpl) Debug(event, obj, opid string, epoch primitive.Timestamp, msg string, args ...any) { +func (discardLoggerImpl) Debug(event, obj, opid string, epoch bson.Timestamp, msg string, args ...any) { } -func (discardLoggerImpl) Info(event, obj, opid string, epoch primitive.Timestamp, msg string, args ...any) { +func (discardLoggerImpl) Info(event, obj, opid string, epoch bson.Timestamp, msg string, args ...any) { } -func (discardLoggerImpl) Warning(event, obj, opid string, epoch primitive.Timestamp, msg string, args ...any) { +func (discardLoggerImpl) Warning(event, obj, opid string, epoch bson.Timestamp, msg string, args ...any) { } -func (discardLoggerImpl) Error(event, obj, opid string, epoch primitive.Timestamp, msg string, args ...any) { +func (discardLoggerImpl) Error(event, obj, opid string, epoch bson.Timestamp, msg string, args ...any) { } -func (discardLoggerImpl) Fatal(event, obj, opid string, epoch primitive.Timestamp, msg string, args ...any) { +func (discardLoggerImpl) Fatal(event, obj, opid string, epoch bson.Timestamp, msg string, args ...any) { } func (discardLoggerImpl) Output(ctx context.Context, e *Entry) error { diff --git a/pbm/log/event.go b/pbm/log/event.go index 595772445..ac9be25ba 100644 --- a/pbm/log/event.go +++ b/pbm/log/event.go @@ -1,15 +1,13 @@ package log -import ( - "go.mongodb.org/mongo-driver/bson/primitive" -) +import "go.mongodb.org/mongo-driver/v2/bson" // eventImpl provides logging for some event (backup, restore) type eventImpl struct { l *loggerImpl typ string obj string - ep primitive.Timestamp + ep bson.Timestamp opid string } diff --git a/pbm/log/history.go b/pbm/log/history.go index d785aaba5..d67a5a369 100644 --- a/pbm/log/history.go +++ b/pbm/log/history.go @@ -7,10 +7,9 @@ import ( "strings" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/errors" @@ -23,10 +22,10 @@ type LogRequest struct { } type Entry struct { - ObjID primitive.ObjectID `bson:"-" json:"-"` // to get sense of mgs total ordering while reading logs - TS int64 `bson:"ts" json:"ts"` - Tns int `bson:"ns" json:"-"` - TZone int `bson:"tz" json:"-"` + ObjID bson.ObjectID `bson:"-" json:"-"` // to get sense of mgs total ordering while reading logs + TS int64 `bson:"ts" json:"ts"` + Tns int `bson:"ns" json:"-"` + TZone int `bson:"tz" json:"-"` LogKeys `bson:",inline" json:",inline"` Msg string `bson:"msg" json:"msg"` } @@ -76,13 +75,13 @@ func AsUTC(ts int64) string { } type LogKeys struct { - Severity Severity `bson:"s" json:"s"` - RS string `bson:"rs" json:"rs"` - Node string `bson:"node" json:"node"` - Event string `bson:"e" json:"e"` - ObjName string `bson:"eobj" json:"eobj"` - Epoch primitive.Timestamp `bson:"ep,omitempty" json:"ep,omitempty"` - OPID string `bson:"opid,omitempty" json:"opid,omitempty"` + Severity Severity `bson:"s" json:"s"` + RS string `bson:"rs" json:"rs"` + Node string `bson:"node" json:"node"` + Event string `bson:"e" json:"e"` + ObjName string `bson:"eobj" json:"eobj"` + Epoch bson.Timestamp `bson:"ep,omitempty" json:"ep,omitempty"` + OPID string `bson:"opid,omitempty" json:"opid,omitempty"` } type Entries struct { diff --git a/pbm/log/log.go b/pbm/log/log.go index ed22277bc..1b92aa729 100644 --- a/pbm/log/log.go +++ b/pbm/log/log.go @@ -4,7 +4,7 @@ import ( "context" "io" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" ) // LogTimeFormat is a date-time format to be displayed in the log output @@ -16,7 +16,7 @@ var ( ) type Logger interface { - NewEvent(typ, name, opid string, epoch primitive.Timestamp) LogEvent + NewEvent(typ, name, opid string, epoch bson.Timestamp) LogEvent NewDefaultEvent() LogEvent Close() @@ -29,11 +29,11 @@ type Logger interface { Write(p []byte) (n int, err error) Printf(msg string, args ...any) - Debug(event, obj, opid string, epoch primitive.Timestamp, msg string, args ...any) - Info(event, obj, opid string, epoch primitive.Timestamp, msg string, args ...any) - Warning(event, obj, opid string, epoch primitive.Timestamp, msg string, args ...any) - Error(event, obj, opid string, epoch primitive.Timestamp, msg string, args ...any) - Fatal(event, obj, opid string, epoch primitive.Timestamp, msg string, args ...any) + Debug(event, obj, opid string, epoch bson.Timestamp, msg string, args ...any) + Info(event, obj, opid string, epoch bson.Timestamp, msg string, args ...any) + Warning(event, obj, opid string, epoch bson.Timestamp, msg string, args ...any) + Error(event, obj, opid string, epoch bson.Timestamp, msg string, args ...any) + Fatal(event, obj, opid string, epoch bson.Timestamp, msg string, args ...any) Output(ctx context.Context, e *Entry) error Opts() *Opts SetLogLevelAndJSON(cfg *Opts) diff --git a/pbm/log/logger.go b/pbm/log/logger.go index 4d12e30db..15da98b4a 100644 --- a/pbm/log/logger.go +++ b/pbm/log/logger.go @@ -15,7 +15,7 @@ import ( "time" "unicode" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/errors" @@ -152,7 +152,7 @@ func (l *loggerImpl) createLogger(logPath string) { } } -func (l *loggerImpl) NewEvent(typ, name, opid string, epoch primitive.Timestamp) LogEvent { +func (l *loggerImpl) NewEvent(typ, name, opid string, epoch bson.Timestamp) LogEvent { return &eventImpl{ l: l, typ: typ, @@ -204,7 +204,7 @@ func (l *loggerImpl) output( event, obj, opid string, - epoch primitive.Timestamp, + epoch bson.Timestamp, msg string, args ...interface{}, ) { @@ -240,26 +240,26 @@ func (l *loggerImpl) output( } func (l *loggerImpl) Printf(msg string, args ...interface{}) { - l.output(Info, "", "", "", primitive.Timestamp{}, msg, args...) + l.output(Info, "", "", "", bson.Timestamp{}, msg, args...) } -func (l *loggerImpl) Debug(event, obj, opid string, epoch primitive.Timestamp, msg string, args ...interface{}) { +func (l *loggerImpl) Debug(event, obj, opid string, epoch bson.Timestamp, msg string, args ...interface{}) { l.output(Debug, event, obj, opid, epoch, msg, args...) } -func (l *loggerImpl) Info(event, obj, opid string, epoch primitive.Timestamp, msg string, args ...interface{}) { +func (l *loggerImpl) Info(event, obj, opid string, epoch bson.Timestamp, msg string, args ...interface{}) { l.output(Info, event, obj, opid, epoch, msg, args...) } -func (l *loggerImpl) Warning(event, obj, opid string, epoch primitive.Timestamp, msg string, args ...interface{}) { +func (l *loggerImpl) Warning(event, obj, opid string, epoch bson.Timestamp, msg string, args ...interface{}) { l.output(Warning, event, obj, opid, epoch, msg, args...) } -func (l *loggerImpl) Error(event, obj, opid string, epoch primitive.Timestamp, msg string, args ...interface{}) { +func (l *loggerImpl) Error(event, obj, opid string, epoch bson.Timestamp, msg string, args ...interface{}) { l.output(Error, event, obj, opid, epoch, msg, args...) } -func (l *loggerImpl) Fatal(event, obj, opid string, epoch primitive.Timestamp, msg string, args ...interface{}) { +func (l *loggerImpl) Fatal(event, obj, opid string, epoch bson.Timestamp, msg string, args ...interface{}) { l.output(Fatal, event, obj, opid, epoch, msg, args...) } diff --git a/pbm/log/logger_test.go b/pbm/log/logger_test.go index a0381c809..cabe5133d 100644 --- a/pbm/log/logger_test.go +++ b/pbm/log/logger_test.go @@ -6,7 +6,7 @@ import ( "strings" "testing" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" ) func TestLoggerConstructor(t *testing.T) { @@ -16,7 +16,7 @@ func TestLoggerConstructor(t *testing.T) { l := NewWithOpts(nil, "rs", "node", &Opts{LogPath: f}) defer os.Remove(f) - l.Debug("", "", "", primitive.Timestamp{}, "msg: %v", "nil conn") + l.Debug("", "", "", bson.Timestamp{}, "msg: %v", "nil conn") lEntry, _ := os.ReadFile(f) if !strings.Contains(string(lEntry), "msg: nil conn") { diff --git a/pbm/oplog/backup.go b/pbm/oplog/backup.go index 0ac359af9..c6d53f1c9 100644 --- a/pbm/oplog/backup.go +++ b/pbm/oplog/backup.go @@ -7,10 +7,9 @@ import ( "sync" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" "github.com/percona/percona-backup-mongodb/pbm/defs" "github.com/percona/percona-backup-mongodb/pbm/errors" @@ -34,8 +33,8 @@ type OplogBackup struct { cl *mongo.Client mu sync.Mutex stopC chan struct{} - start primitive.Timestamp - end primitive.Timestamp + start bson.Timestamp + end bson.Timestamp } // NewOplogBackup creates a new Oplog instance @@ -44,13 +43,13 @@ func NewOplogBackup(m *mongo.Client) *OplogBackup { } // SetTailingSpan sets oplog tailing window -func (ot *OplogBackup) SetTailingSpan(start, end primitive.Timestamp) { +func (ot *OplogBackup) SetTailingSpan(start, end bson.Timestamp) { ot.start = start ot.end = end } type InsuffRangeError struct { - primitive.Timestamp + bson.Timestamp } func (e InsuffRangeError) Error() string { @@ -100,7 +99,7 @@ func (ot *OplogBackup) WriteTo(w io.Writer) (int64, error) { } defer cur.Close(ctx) - opts := primitive.Timestamp{} + opts := bson.Timestamp{} var ok, rcheck bool var written int64 for cur.Next(ctx) { @@ -167,7 +166,7 @@ func (ot *OplogBackup) Cancel() { } // IsSufficient check is oplog is sufficient back from the given date -func (ot *OplogBackup) IsSufficient(from primitive.Timestamp) (bool, error) { +func (ot *OplogBackup) IsSufficient(from bson.Timestamp) (bool, error) { c, err := ot.cl.Database("local").Collection("oplog.rs"). CountDocuments(context.Background(), bson.M{"ts": bson.M{"$lte": from}}, diff --git a/pbm/oplog/chunk.go b/pbm/oplog/chunk.go index 6f1b2a2a0..1beeeadb7 100644 --- a/pbm/oplog/chunk.go +++ b/pbm/oplog/chunk.go @@ -8,12 +8,12 @@ import ( "strings" "time" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" + "github.com/percona/percona-backup-mongodb/pbm/log" "github.com/percona/percona-backup-mongodb/pbm/storage" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" "github.com/percona/percona-backup-mongodb/pbm/compress" "github.com/percona/percona-backup-mongodb/pbm/connect" @@ -27,8 +27,8 @@ type OplogChunk struct { RS string `bson:"rs"` FName string `bson:"fname"` Compression compress.CompressionType `bson:"compression"` - StartTS primitive.Timestamp `bson:"start_ts"` - EndTS primitive.Timestamp `bson:"end_ts"` + StartTS bson.Timestamp `bson:"start_ts"` + EndTS bson.Timestamp `bson:"end_ts"` Size int64 `bson:"size"` } @@ -60,7 +60,7 @@ func pitrChunk(ctx context.Context, m connect.Client, rs string, sort int) (*Opl return chnk, errors.Wrap(err, "decode") } -func AllOplogRSNames(ctx context.Context, m connect.Client, from, to primitive.Timestamp) ([]string, error) { +func AllOplogRSNames(ctx context.Context, m connect.Client, from, to bson.Timestamp) ([]string, error) { q := bson.M{ "start_ts": bson.M{"$lte": to}, } @@ -68,14 +68,14 @@ func AllOplogRSNames(ctx context.Context, m connect.Client, from, to primitive.T q["end_ts"] = bson.M{"$gte": from} } - res, err := m.PITRChunksCollection().Distinct(ctx, "rs", q) - if err != nil { + res := m.PITRChunksCollection().Distinct(ctx, "rs", q) + if err := res.Err(); err != nil { return nil, errors.Wrapf(err, "query") } - rv := make([]string, len(res)) - for i, rs := range res { - rv[i] = rs.(string) + var rv []string + if err := res.Decode(&rv); err != nil { + return nil, errors.Wrap(err, "decode distinct") } return rv, nil @@ -87,7 +87,7 @@ func PITRGetChunksSlice( ctx context.Context, m connect.Client, rs string, - from, to primitive.Timestamp, + from, to bson.Timestamp, ) ([]OplogChunk, error) { q := bson.D{} if rs != "" { @@ -108,7 +108,7 @@ func PITRGetChunksSliceUntil( ctx context.Context, m connect.Client, rs string, - t primitive.Timestamp, + t bson.Timestamp, ) ([]OplogChunk, error) { q := bson.D{} if rs != "" { @@ -151,7 +151,7 @@ func PITRGetChunkStarts( ctx context.Context, m connect.Client, rs string, - ts primitive.Timestamp, + ts bson.Timestamp, ) (*OplogChunk, error) { res := m.PITRChunksCollection().FindOne( ctx, @@ -186,7 +186,7 @@ func PITRGetValidTimelines( ctx context.Context, m connect.Client, rs string, - until primitive.Timestamp, + until bson.Timestamp, ) ([]Timeline, error) { fch, err := PITRFirstChunkMeta(ctx, m, rs) if err != nil && !errors.Is(err, errors.ErrNotFound) { @@ -203,8 +203,8 @@ func PITRGetValidTimelinesBetween( ctx context.Context, m connect.Client, rs string, - from primitive.Timestamp, - until primitive.Timestamp, + from bson.Timestamp, + until bson.Timestamp, ) ([]Timeline, error) { slices, err := PITRGetChunksSlice(ctx, m, rs, from, until) if err != nil { @@ -221,10 +221,10 @@ func PITRTimelines(ctx context.Context, m connect.Client) ([]Timeline, error) { return nil, errors.Wrap(err, "get cluster time") } - return PITRTimelinesBetween(ctx, m, primitive.Timestamp{}, now) + return PITRTimelinesBetween(ctx, m, bson.Timestamp{}, now) } -func PITRTimelinesBetween(ctx context.Context, m connect.Client, from, until primitive.Timestamp) ([]Timeline, error) { +func PITRTimelinesBetween(ctx context.Context, m connect.Client, from, until bson.Timestamp) ([]Timeline, error) { shards, err := topo.ClusterMembers(ctx, m.MongoClient()) if err != nil { return nil, errors.Wrap(err, "get cluster members") @@ -246,7 +246,7 @@ func PITRTimelinesBetween(ctx context.Context, m connect.Client, from, until pri func gettimelines(slices []OplogChunk) []Timeline { var tl Timeline - var prevEnd primitive.Timestamp + var prevEnd bson.Timestamp tlines := []Timeline{} for _, s := range slices { @@ -391,7 +391,7 @@ func MergeTimelines(tlns ...[]Timeline) []Timeline { // Current format is 20200715155939-0.20200715160029-1.oplog.snappy // // !!! should be agreed with oplog.MakeChunkMetaFromFilepath() -func FormatChunkFilepath(rs string, first, last primitive.Timestamp, c compress.CompressionType) string { +func FormatChunkFilepath(rs string, first, last bson.Timestamp, c compress.CompressionType) string { ft := time.Unix(int64(first.T), 0).UTC() lt := time.Unix(int64(last.T), 0).UTC() @@ -455,14 +455,14 @@ func MakeChunkMetaFromFilepath(f string) *OplogChunk { return chnk } -func pitrParseTS(tstr string) *primitive.Timestamp { +func pitrParseTS(tstr string) *bson.Timestamp { tparts := strings.Split(tstr, "-") t, err := time.Parse("20060102150405", tparts[0]) if err != nil { // just skip this file return nil } - ts := primitive.Timestamp{T: uint32(t.Unix())} + ts := bson.Timestamp{T: uint32(t.Unix())} if len(tparts) > 1 { ti, err := strconv.Atoi(tparts[1]) if err != nil { diff --git a/pbm/oplog/chunk_test.go b/pbm/oplog/chunk_test.go index f06f27eab..cf5e6b1bf 100644 --- a/pbm/oplog/chunk_test.go +++ b/pbm/oplog/chunk_test.go @@ -5,38 +5,38 @@ import ( "strings" "testing" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" ) func TestPITRTimelines(t *testing.T) { chunks := []OplogChunk{ { - StartTS: primitive.Timestamp{1, 0}, - EndTS: primitive.Timestamp{10, 0}, + StartTS: bson.Timestamp{1, 0}, + EndTS: bson.Timestamp{10, 0}, }, { - StartTS: primitive.Timestamp{10, 0}, - EndTS: primitive.Timestamp{10, 0}, + StartTS: bson.Timestamp{10, 0}, + EndTS: bson.Timestamp{10, 0}, }, { - StartTS: primitive.Timestamp{10, 0}, - EndTS: primitive.Timestamp{20, 0}, + StartTS: bson.Timestamp{10, 0}, + EndTS: bson.Timestamp{20, 0}, }, { - StartTS: primitive.Timestamp{30, 0}, - EndTS: primitive.Timestamp{40, 0}, + StartTS: bson.Timestamp{30, 0}, + EndTS: bson.Timestamp{40, 0}, }, { - StartTS: primitive.Timestamp{666, 0}, - EndTS: primitive.Timestamp{779, 0}, + StartTS: bson.Timestamp{666, 0}, + EndTS: bson.Timestamp{779, 0}, }, { - StartTS: primitive.Timestamp{777, 0}, - EndTS: primitive.Timestamp{988, 0}, + StartTS: bson.Timestamp{777, 0}, + EndTS: bson.Timestamp{988, 0}, }, { - StartTS: primitive.Timestamp{888, 0}, - EndTS: primitive.Timestamp{1000, 0}, + StartTS: bson.Timestamp{888, 0}, + EndTS: bson.Timestamp{1000, 0}, }, } diff --git a/pbm/oplog/db.go b/pbm/oplog/db.go index 138e98528..8c20da27f 100644 --- a/pbm/oplog/db.go +++ b/pbm/oplog/db.go @@ -4,9 +4,8 @@ import ( "context" "strings" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/errors" ) @@ -23,8 +22,8 @@ func newMDB(m *mongo.Client) *mDB { // getUUIDForNS ruturns UUID of existing collection. // When ns doesn't exist, it returns zero value without an error. // In case of error, it returns zero value for UUID in addition to error. -func (d *mDB) getUUIDForNS(ctx context.Context, ns string) (primitive.Binary, error) { - var uuid primitive.Binary +func (d *mDB) getUUIDForNS(ctx context.Context, ns string) (bson.Binary, error) { + var uuid bson.Binary db, coll, _ := strings.Cut(ns, ".") cur, err := d.m.Database(db).ListCollections(ctx, bson.D{{"name", coll}}) @@ -35,7 +34,7 @@ func (d *mDB) getUUIDForNS(ctx context.Context, ns string) (primitive.Binary, er for cur.Next(ctx) { if subtype, data, ok := cur.Current.Lookup("info", "uuid").BinaryOK(); ok { - uuid = primitive.Binary{ + uuid = bson.Binary{ Subtype: subtype, Data: data, } diff --git a/pbm/oplog/db_tc_test.go b/pbm/oplog/db_tc_test.go index fa2697209..34c972752 100644 --- a/pbm/oplog/db_tc_test.go +++ b/pbm/oplog/db_tc_test.go @@ -9,9 +9,9 @@ import ( "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/mongodb" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" ) var mClient *mongo.Client @@ -26,7 +26,7 @@ func TestMain(m *testing.M) { if err != nil { log.Fatalf("conn string error: %v", err) } - mClient, err = mongo.Connect(ctx, options.Client().ApplyURI(connStr)) + mClient, err = mongo.Connect(options.Client().ApplyURI(connStr)) if err != nil { log.Fatalf("mongo client connect error: %v", err) } diff --git a/pbm/oplog/db_test.go b/pbm/oplog/db_test.go deleted file mode 100644 index 6848cbb73..000000000 --- a/pbm/oplog/db_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package oplog - -import ( - "context" - "strings" - "testing" - - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo/integration/mtest" -) - -func TestGetUUIDForNS(t *testing.T) { - mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock)) - - mt.Run("successful response from db", func(mt *mtest.T) { - expectedUUID := primitive.Binary{Subtype: 0xFF, Data: []byte{0x01, 0x02, 0x03}} - listCollRes := bson.D{ - {"name", "c1"}, - {"type", "collection"}, - {"info", bson.D{ - {"readOnly", false}, - {"uuid", expectedUUID}, - }}, - } - mt.AddMockResponses(mtest.CreateCursorResponse(1, "mydb.c1", mtest.FirstBatch, listCollRes)) - - db := newMDB(mt.Client) - uuid, err := db.getUUIDForNS(context.Background(), "mydb.c1") - if err != nil { - t.Errorf("got err=%v", err) - } - primitive.NewObjectID() - - if !uuid.Equal(expectedUUID) { - t.Errorf("wrong uuid for ns: expected=%v, got=%v", expectedUUID, uuid) - } - t.Log(uuid) - }) - - mt.Run("failed response from db", func(mt *mtest.T) { - errRes := mtest.CreateCommandErrorResponse(mtest.CommandError{ - Code: 11601, - Name: "error", - Message: "querying list collections", - }) - mt.AddMockResponses(errRes) - db := newMDB(mt.Client) - _, err := db.getUUIDForNS(context.Background(), "mydb.c1") - if err == nil { - t.Error("expected to get error from getUUIDForNS") - } - if !strings.Contains(err.Error(), "list collections") { - t.Error("wrong err") - } - }) -} diff --git a/pbm/oplog/nomination.go b/pbm/oplog/nomination.go index 22766700d..ab74381a7 100644 --- a/pbm/oplog/nomination.go +++ b/pbm/oplog/nomination.go @@ -5,10 +5,9 @@ import ( "fmt" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/errors" @@ -17,11 +16,11 @@ import ( // PITRMeta contains all operational data about PITR execution process. type PITRMeta struct { - StartTS int64 `bson:"start_ts" json:"start_ts"` - Hb primitive.Timestamp `bson:"hb" json:"hb"` - Status Status `bson:"status" json:"status"` - Nomination []PITRNomination `bson:"n" json:"n"` - Replsets []PITRReplset `bson:"replsets" json:"replsets"` + StartTS int64 `bson:"start_ts" json:"start_ts"` + Hb bson.Timestamp `bson:"hb" json:"hb"` + Status Status `bson:"status" json:"status"` + Nomination []PITRNomination `bson:"n" json:"n"` + Replsets []PITRReplset `bson:"replsets" json:"replsets"` } // PITRNomination is used to choose (nominate and elect) member(s) @@ -108,7 +107,7 @@ func SetClusterStatus(ctx context.Context, conn connect.Client, status Status) e "status": status, "replsets": []PITRReplset{}, }}}, - options.Update().SetUpsert(true), + options.UpdateOne().SetUpsert(true), ) return errors.Wrap(err, "update pitr doc to status") } @@ -137,7 +136,7 @@ func SetReadyRSStatus(ctx context.Context, conn connect.Client, rs, node string) ctx, bson.D{}, bson.D{{"$addToSet", bson.M{"replsets": repliset}}}, - options.Update().SetUpsert(true), + options.UpdateOne().SetUpsert(true), ) return errors.Wrap(err, "update pitr doc for RS ready status") } @@ -155,7 +154,7 @@ func SetErrorRSStatus(ctx context.Context, conn connect.Client, rs, node, errTex ctx, bson.D{}, bson.D{{"$addToSet", bson.M{"replsets": repliset}}}, - options.Update().SetUpsert(true), + options.UpdateOne().SetUpsert(true), ) return errors.Wrap(err, "update pitr doc for RS error status") } @@ -187,7 +186,7 @@ func SetPITRNomination(ctx context.Context, conn connect.Client, rs string) erro ctx, bson.D{}, bson.D{{"$addToSet", bson.M{"n": n}}}, - options.Update().SetUpsert(true), + options.UpdateOne().SetUpsert(true), ) return errors.Wrap(err, "update pitr nomination") } diff --git a/pbm/oplog/oplog.go b/pbm/oplog/oplog.go index 14e6264d8..c76a71c26 100644 --- a/pbm/oplog/oplog.go +++ b/pbm/oplog/oplog.go @@ -4,11 +4,10 @@ import ( "context" "fmt" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" - "go.mongodb.org/mongo-driver/mongo/readconcern" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" + "go.mongodb.org/mongo-driver/v2/mongo/readconcern" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/ctrl" @@ -20,7 +19,7 @@ import ( var errNoTransaction = errors.New("no transaction found") -func GetOplogStartTime(ctx context.Context, m *mongo.Client) (primitive.Timestamp, error) { +func GetOplogStartTime(ctx context.Context, m *mongo.Client) (bson.Timestamp, error) { ts, err := findTransactionStartTime(ctx, m) if errors.Is(err, errNoTransaction) { ts, err = findLastOplogTS(ctx, m) @@ -29,50 +28,50 @@ func GetOplogStartTime(ctx context.Context, m *mongo.Client) (primitive.Timestam return ts, err } -func findTransactionStartTime(ctx context.Context, m *mongo.Client) (primitive.Timestamp, error) { +func findTransactionStartTime(ctx context.Context, m *mongo.Client) (bson.Timestamp, error) { coll := m.Database("config").Collection("transactions", options.Collection().SetReadConcern(readconcern.Local())) f := bson.D{{"state", bson.D{{"$in", bson.A{"prepared", "inProgress"}}}}} o := options.FindOne().SetSort(bson.D{{"startOpTime", 1}}) doc, err := coll.FindOne(ctx, f, o).Raw() if err != nil { if errors.Is(err, mongo.ErrNoDocuments) { - return primitive.Timestamp{}, errNoTransaction + return bson.Timestamp{}, errNoTransaction } - return primitive.Timestamp{}, errors.Wrap(err, "query transactions") + return bson.Timestamp{}, errors.Wrap(err, "query transactions") } rawTS, err := doc.LookupErr("startOpTime", "ts") if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "lookup timestamp") + return bson.Timestamp{}, errors.Wrap(err, "lookup timestamp") } t, i, ok := rawTS.TimestampOK() if !ok { - return primitive.Timestamp{}, errors.Wrap(err, "parse timestamp") + return bson.Timestamp{}, errors.Wrap(err, "parse timestamp") } - return primitive.Timestamp{T: t, I: i}, nil + return bson.Timestamp{T: t, I: i}, nil } -func findLastOplogTS(ctx context.Context, m *mongo.Client) (primitive.Timestamp, error) { +func findLastOplogTS(ctx context.Context, m *mongo.Client) (bson.Timestamp, error) { coll := m.Database("local").Collection("oplog.rs") o := options.FindOne().SetSort(bson.M{"$natural": -1}) doc, err := coll.FindOne(ctx, bson.D{}, o).Raw() if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "query oplog") + return bson.Timestamp{}, errors.Wrap(err, "query oplog") } rawTS, err := doc.LookupErr("ts") if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "lookup oplog ts") + return bson.Timestamp{}, errors.Wrap(err, "lookup oplog ts") } t, i, ok := rawTS.TimestampOK() if !ok { - return primitive.Timestamp{}, errors.Wrap(err, "parse oplog ts") + return bson.Timestamp{}, errors.Wrap(err, "parse oplog ts") } - return primitive.Timestamp{T: t, I: i}, nil + return bson.Timestamp{T: t, I: i}, nil } // IsOplogSlicing checks if PITR slicing is running. It looks for PITR locks diff --git a/pbm/oplog/restore.go b/pbm/oplog/restore.go index e8067e62d..fa47722fe 100644 --- a/pbm/oplog/restore.go +++ b/pbm/oplog/restore.go @@ -25,11 +25,11 @@ import ( "github.com/mongodb/mongo-tools/common/idx" "github.com/mongodb/mongo-tools/common/txn" "github.com/mongodb/mongo-tools/mongorestore/ns" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "github.com/percona/percona-backup-mongodb/pbm/log" "github.com/percona/percona-backup-mongodb/pbm/topo" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" "github.com/percona/percona-backup-mongodb/pbm/defs" "github.com/percona/percona-backup-mongodb/pbm/errors" @@ -131,7 +131,7 @@ type cloneNS struct { fromColl string toDB string toColl string - toUUID primitive.Binary + toUUID bson.Binary } func (c *cloneNS) SetNSPair(nsPair snapshot.CloneNS) { @@ -142,7 +142,7 @@ func (c *cloneNS) SetNSPair(nsPair snapshot.CloneNS) { // mDBCl represents client interface for MongoDB logic used by OplogRestore type mDBCl interface { - getUUIDForNS(ctx context.Context, ns string) (primitive.Binary, error) + getUUIDForNS(ctx context.Context, ns string) (bson.Binary, error) ensureCollExists(dbName string) error applyOps(entries []interface{}) error } @@ -152,8 +152,8 @@ type OplogRestore struct { mdb mDBCl ver *db.Version needIdxWorkaround bool - startTS primitive.Timestamp - endTS primitive.Timestamp + startTS bson.Timestamp + endTS bson.Timestamp indexCatalog *idx.IndexCatalog excludeNS *ns.Matcher includeNS map[string]map[string]bool @@ -237,19 +237,19 @@ func (o *OplogRestore) SetSelectiveUsersAndRolesRestore(u bool) { // SetTimeframe sets boundaries for the replayed operations. All operations // that happened before `start` and after `end` are going to be discarded. -// Zero `end` (primitive.Timestamp{T:0}) means all chunks will be replayed +// Zero `end` (bson.Timestamp{T:0}) means all chunks will be replayed // utill the end (no tail trim). -func (o *OplogRestore) SetTimeframe(start, end primitive.Timestamp) { +func (o *OplogRestore) SetTimeframe(start, end bson.Timestamp) { o.startTS = start o.endTS = end } // Apply applys an oplog from a given source -func (o *OplogRestore) Apply(src io.ReadCloser) (primitive.Timestamp, error) { +func (o *OplogRestore) Apply(src io.ReadCloser) (bson.Timestamp, error) { bsonSource := db.NewDecodedBSONSource(db.NewBufferlessBSONSource(src)) defer bsonSource.Close() - var lts primitive.Timestamp + var lts bson.Timestamp for { rawOplogEntry := bsonSource.LoadNext() @@ -442,7 +442,7 @@ func isConfigCollectionsDocAllowed(oe *Record, sessUUID *string) bool { continue } - oeUUID, ok := e.Value.(primitive.Binary) + oeUUID, ok := e.Value.(bson.Binary) if !ok { return true } @@ -484,7 +484,7 @@ func isConfigChunksDocAllowed(oe *Record, sessUUID string) bool { continue } - oeUUID, ok := e.Value.(primitive.Binary) + oeUUID, ok := e.Value.(bson.Binary) if !ok { return true } @@ -852,10 +852,10 @@ func (o *OplogRestore) handleTxnOp(meta txn.Meta, op db.Oplog) error { // preserve it and communicate later to another shards so they can apply // prepared txn if its commit didn't get into the oplog time range if !meta.IsData() { - var cts primitive.Timestamp + var cts bson.Timestamp for _, v := range op.Object { if v.Key == "commitTimestamp" { - cts = v.Value.(primitive.Timestamp) + cts = v.Value.(bson.Timestamp) } } @@ -915,7 +915,8 @@ func txnInnerOps(txnOp *db.Oplog) ([]db.Oplog, error) { // so we are assigning them from the parent transaction op op.Timestamp = txnOp.Timestamp op.Term = txnOp.Term - op.Hash = txnOp.Hash + // migration mongo-driver v1->v2: fix this in PBM-1682 + // op.Hash = txnOp.Hash ops[i] = *op } @@ -962,7 +963,7 @@ func bsonDocToOplog(doc bson.D) (*db.Oplog, error) { } op.Query = d case "ui": - u, ok := v.Value.(primitive.Binary) + u, ok := v.Value.(bson.Binary) if !ok { return nil, bsonConvertError{"ui field", "not binary data"} } @@ -997,7 +998,7 @@ func (o *OplogRestore) TxnLeftovers() (uncommitted map[string]Txn, lastCommits [ //nolint:nonamedreturns func (o *OplogRestore) HandleUncommittedTxn( - commits map[string]primitive.Timestamp, + commits map[string]bson.Timestamp, ) (partial, uncommitted []Txn, err error) { if len(o.txnData) == 0 { return nil, nil, nil @@ -1275,7 +1276,8 @@ func extractIndexDocumentFromCreateIndexes(op db.Oplog) (string, *idx.IndexDocum case "key": indexDocument.Key = elem.Value.(bson.D) case "partialFilterExpression": - indexDocument.PartialFilterExpression = elem.Value.(bson.D) + v := elem.Value.(bson.D) + indexDocument.PartialFilterExpression = &v default: indexDocument.Options[elem.Key] = elem.Value } @@ -1308,7 +1310,8 @@ func extractIndexDocumentFromCommitIndexBuilds(op db.Oplog) (string, []*idx.Inde case "key": indexSpec.Key = elem.Value.(bson.D) case "partialFilterExpression": - indexSpec.PartialFilterExpression = elem.Value.(bson.D) + v := elem.Value.(bson.D) + indexSpec.PartialFilterExpression = &v default: indexSpec.Options[elem.Key] = elem.Value } @@ -1475,7 +1478,7 @@ func isTruthy(val interface{}) bool { if val == nil { return false } - if val == (primitive.Undefined{}) { + if val == (bson.Undefined{}) { return false } diff --git a/pbm/oplog/restore_test.go b/pbm/oplog/restore_test.go index 012ad218f..8321e08ce 100644 --- a/pbm/oplog/restore_test.go +++ b/pbm/oplog/restore_test.go @@ -13,13 +13,12 @@ import ( "github.com/mongodb/mongo-tools/common/db" "github.com/mongodb/mongo-tools/common/idx" "github.com/mongodb/mongo-tools/mongorestore/ns" - "github.com/percona/percona-backup-mongodb/pbm/log" - "github.com/percona/percona-backup-mongodb/pbm/topo" "github.com/pkg/errors" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" + "github.com/percona/percona-backup-mongodb/pbm/log" "github.com/percona/percona-backup-mongodb/pbm/snapshot" + "github.com/percona/percona-backup-mongodb/pbm/topo" ) func newOplogRestoreTest(mdb mDBCl) *OplogRestore { @@ -45,8 +44,8 @@ func newMDBTestClient() *mdbTestClient { return &mdbTestClient{applyOpsInv: []map[string]string{}} } -func (d *mdbTestClient) getUUIDForNS(_ context.Context, _ string) (primitive.Binary, error) { - return primitive.Binary{Subtype: 0x00, Data: []byte{0x01, 0x02, 0x03}}, nil +func (d *mdbTestClient) getUUIDForNS(_ context.Context, _ string) (bson.Binary, error) { + return bson.Binary{Subtype: 0x00, Data: []byte{0x01, 0x02, 0x03}}, nil } func (d *mdbTestClient) ensureCollExists(_ string) error { @@ -1098,7 +1097,7 @@ func createConfigCollectionsEntry(shardedColl, collUUID string) *db.Oplog { Namespace: "config.collections", Object: bson.D{ {"_id", shardedColl}, - {"uuid", primitive.Binary{Subtype: bson.TypeBinaryUUID, Data: uuid}}, + {"uuid", bson.Binary{Subtype: bson.TypeBinaryUUID, Data: uuid}}, }, } } @@ -1111,7 +1110,7 @@ func createConfigChunksEntry(uuid string) *db.Oplog { Namespace: "config.chunks", Object: bson.D{ {"_id", id}, - {"uuid", primitive.Binary{Subtype: bson.TypeBinaryUUID, Data: uuidDecoded}}, + {"uuid", bson.Binary{Subtype: bson.TypeBinaryUUID, Data: uuidDecoded}}, {"shard", "rsX"}, }, } diff --git a/pbm/restore/logical.go b/pbm/restore/logical.go index f68ecc21b..af16f2b4a 100644 --- a/pbm/restore/logical.go +++ b/pbm/restore/logical.go @@ -14,9 +14,8 @@ import ( "github.com/mongodb/mongo-tools/common/db" "github.com/mongodb/mongo-tools/common/idx" "github.com/mongodb/mongo-tools/mongorestore" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/archive" "github.com/percona/percona-backup-mongodb/pbm/backup" @@ -729,7 +728,7 @@ func (r *Restore) checkTopologyForOplog(currShards []topo.Shard, oplogShards []s // chunks defines chunks of oplog slice in given range, ensures its integrity (timeline // is contiguous - there are no gaps), checks for respective files on storage and returns // chunks list if all checks passed -func (r *Restore) chunks(ctx context.Context, from, to primitive.Timestamp) ([]oplog.OplogChunk, error) { +func (r *Restore) chunks(ctx context.Context, from, to bson.Timestamp) ([]oplog.OplogChunk, error) { return chunks(ctx, r.leadConn, r.oplogStg, from, to, r.nodeInfo.SetName, r.rsMap) } @@ -949,7 +948,7 @@ func (r *Restore) fullRestoreDBCleanup(ctx context.Context, bcp *backup.BackupMe err = r.db.runCmdShardsvrDropDatabase(ctx, db, configDBDoc) if err != nil { - return errors.Wrap(err, "full restore cleanup") + return errors.Wrap(err, "run cmd") } r.log.Debug("drop %q", db) } @@ -1366,12 +1365,12 @@ func updateRouterTables(ctx context.Context, m connect.Client, sMap map[string]s func updateDatabasesRouterTable(ctx context.Context, m connect.Client, sMap map[string]string) error { coll := m.ConfigDatabase().Collection("databases") - oldNames := make(primitive.A, 0, len(sMap)) + oldNames := make(bson.A, 0, len(sMap)) for k := range sMap { oldNames = append(oldNames, k) } - q := primitive.M{"primary": primitive.M{"$in": oldNames}} + q := bson.M{"primary": bson.M{"$in": oldNames}} cur, err := coll.Find(ctx, q) if err != nil { return errors.Wrap(err, "query") @@ -1388,8 +1387,8 @@ func updateDatabasesRouterTable(ctx context.Context, m connect.Client, sMap map[ } m := mongo.NewUpdateOneModel() - m.SetFilter(primitive.M{"_id": doc.ID}) - m.SetUpdate(primitive.M{"$set": primitive.M{"primary": sMap[doc.Primary]}}) + m.SetFilter(bson.M{"_id": doc.ID}) + m.SetUpdate(bson.M{"$set": bson.M{"primary": sMap[doc.Primary]}}) models = append(models, m) } @@ -1407,12 +1406,12 @@ func updateDatabasesRouterTable(ctx context.Context, m connect.Client, sMap map[ func updateChunksRouterTable(ctx context.Context, m connect.Client, sMap map[string]string) error { coll := m.ConfigDatabase().Collection("chunks") - oldNames := make(primitive.A, 0, len(sMap)) + oldNames := make(bson.A, 0, len(sMap)) for k := range sMap { oldNames = append(oldNames, k) } - q := primitive.M{"history.shard": primitive.M{"$in": oldNames}} + q := bson.M{"history.shard": bson.M{"$in": oldNames}} cur, err := coll.Find(ctx, q) if err != nil { return errors.Wrap(err, "query") @@ -1431,7 +1430,7 @@ func updateChunksRouterTable(ctx context.Context, m connect.Client, sMap map[str return errors.Wrap(err, "decode") } - updates := primitive.M{} + updates := bson.M{} if n, ok := sMap[doc.Shard]; ok { updates["shard"] = n } @@ -1443,8 +1442,8 @@ func updateChunksRouterTable(ctx context.Context, m connect.Client, sMap map[str } m := mongo.NewUpdateOneModel() - m.SetFilter(primitive.M{"_id": doc.ID}) - m.SetUpdate(primitive.M{"$set": updates}) + m.SetFilter(bson.M{"_id": doc.ID}) + m.SetUpdate(bson.M{"$set": updates}) models = append(models, m) } if err := cur.Err(); err != nil { @@ -1462,8 +1461,8 @@ func (r *Restore) setcommittedTxn(ctx context.Context, txn []phys.RestoreTxn) er return RestoreSetRSTxn(ctx, r.leadConn, r.name, r.nodeInfo.SetName, txn) } -func (r *Restore) getcommittedTxn(ctx context.Context) (map[string]primitive.Timestamp, error) { - txn := make(map[string]primitive.Timestamp) +func (r *Restore) getcommittedTxn(ctx context.Context) (map[string]bson.Timestamp, error) { + txn := make(map[string]bson.Timestamp) shards := make(map[string]struct{}) for _, s := range r.shards { diff --git a/pbm/restore/logical_cfgsvr_full.go b/pbm/restore/logical_cfgsvr_full.go index 746e03051..edfa10f85 100644 --- a/pbm/restore/logical_cfgsvr_full.go +++ b/pbm/restore/logical_cfgsvr_full.go @@ -6,9 +6,8 @@ import ( "io" "path" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/archive" "github.com/percona/percona-backup-mongodb/pbm/backup" @@ -349,7 +348,7 @@ func (r *Restore) cleanUpConfigChunks(ctx context.Context) error { excSessFilter := bson.M{} if sessBson != nil { if subtype, uuid, ok := sessBson.Lookup("uuid").BinaryOK(); ok { - uuid := primitive.Binary{Subtype: subtype, Data: uuid} + uuid := bson.Binary{Subtype: subtype, Data: uuid} excSessFilter["uuid"] = bson.M{"$ne": uuid} } } diff --git a/pbm/restore/logical_cfgsvr_full_test.go b/pbm/restore/logical_cfgsvr_full_test.go index 5f9b47dcc..b3fcefded 100644 --- a/pbm/restore/logical_cfgsvr_full_test.go +++ b/pbm/restore/logical_cfgsvr_full_test.go @@ -9,8 +9,7 @@ import ( "testing" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/backup" "github.com/percona/percona-backup-mongodb/pbm/compress" @@ -291,9 +290,9 @@ func createConfigDatabasesDocs(t *testing.T, n int64) *bytes.Buffer { t.Helper() type version struct { - UUID primitive.Binary `bson:"uuid"` - Timestamp primitive.Timestamp `bson:"timestamp"` - LastMod int64 `bson:"lastMod,omitempty"` + UUID bson.Binary `bson:"uuid"` + Timestamp bson.Timestamp `bson:"timestamp"` + LastMod int64 `bson:"lastMod,omitempty"` } type databasesSchema struct { ID string `bson:"_id"` @@ -307,8 +306,8 @@ func createConfigDatabasesDocs(t *testing.T, n int64) *bytes.Buffer { ID: fmt.Sprintf("%d", i), Primary: "rs1", Version: version{ - UUID: primitive.Binary{Subtype: 0x04, Data: fmt.Appendf([]byte("abcd"), "%d", i)}, - Timestamp: primitive.Timestamp{T: uint32(i), I: 1}, + UUID: bson.Binary{Subtype: 0x04, Data: fmt.Appendf([]byte("abcd"), "%d", i)}, + Timestamp: bson.Timestamp{T: uint32(i), I: 1}, LastMod: i, }, } @@ -328,25 +327,25 @@ func createConfigCollectionsDocs(t *testing.T, n int64, addSession bool) *bytes. t.Helper() type collectionsSchema struct { - ID string `bson:"_id"` - LastmodEpoch primitive.ObjectID `bson:"lastmodEpoch"` - LastMod primitive.DateTime `bson:"lastMod"` - Timestamp primitive.Timestamp `bson:"timestamp"` - UUID primitive.Binary `bson:"uuid,omitempty"` - Key bson.D `bson:"key"` - Unique bool `bson:"unique"` - NoBalance bool `bson:"noBalance"` - MaxChunkSizeBytes int64 `bson:"maxChunkSizeBytes"` + ID string `bson:"_id"` + LastmodEpoch bson.ObjectID `bson:"lastmodEpoch"` + LastMod bson.DateTime `bson:"lastMod"` + Timestamp bson.Timestamp `bson:"timestamp"` + UUID bson.Binary `bson:"uuid,omitempty"` + Key bson.D `bson:"key"` + Unique bool `bson:"unique"` + NoBalance bool `bson:"noBalance"` + MaxChunkSizeBytes int64 `bson:"maxChunkSizeBytes"` } b := &bytes.Buffer{} for i := range n { dbDoc := collectionsSchema{ ID: fmt.Sprintf("%d", i), - LastmodEpoch: primitive.NewObjectID(), + LastmodEpoch: bson.NewObjectID(), LastMod: 10, - Timestamp: primitive.Timestamp{T: uint32(i), I: 1}, - UUID: primitive.Binary{Subtype: 0x04, Data: fmt.Appendf([]byte("abcd"), "%d", i)}, + Timestamp: bson.Timestamp{T: uint32(i), I: 1}, + UUID: bson.Binary{Subtype: 0x04, Data: fmt.Appendf([]byte("abcd"), "%d", i)}, Key: bson.D{{"_id", 1}}, Unique: false, NoBalance: false, @@ -355,7 +354,7 @@ func createConfigCollectionsDocs(t *testing.T, n int64, addSession bool) *bytes. if addSession && i == 0 { dbDoc.ID = "config.system.sessions" uuid, _ := hex.DecodeString(configSystemSessionsUUID) - dbDoc.UUID = primitive.Binary{Subtype: 0x04, Data: uuid} + dbDoc.UUID = bson.Binary{Subtype: 0x04, Data: uuid} } bsonDoc, err := bson.Marshal(dbDoc) if err != nil { @@ -373,39 +372,39 @@ func createConfigChunksDocs(t *testing.T, n int64, addSessionChunk bool, sysSess t.Helper() type historyEntry struct { - ValidAfter primitive.Timestamp `bson:"validAfter"` - Shard string `bson:"shard"` + ValidAfter bson.Timestamp `bson:"validAfter"` + Shard string `bson:"shard"` } type chunksSchema struct { - ID primitive.ObjectID `bson:"_id"` - UUID primitive.Binary `bson:"uuid"` - Min bson.D `bson:"min"` - Max bson.D `bson:"max"` - Shard string `bson:"shard"` - Lastmod primitive.Timestamp `bson:"lastmod"` - OnCurrentShardSince primitive.Timestamp `bson:"onCurrentShardSince"` - History []historyEntry `bson:"history"` + ID bson.ObjectID `bson:"_id"` + UUID bson.Binary `bson:"uuid"` + Min bson.D `bson:"min"` + Max bson.D `bson:"max"` + Shard string `bson:"shard"` + Lastmod bson.Timestamp `bson:"lastmod"` + OnCurrentShardSince bson.Timestamp `bson:"onCurrentShardSince"` + History []historyEntry `bson:"history"` } b := &bytes.Buffer{} for i := range n { - uuid := primitive.Binary{Subtype: 0x04, Data: fmt.Appendf([]byte("abcd"), "%d", i)} + uuid := bson.Binary{Subtype: 0x04, Data: fmt.Appendf([]byte("abcd"), "%d", i)} if addSessionChunk && i == 0 { uuidBytes, _ := hex.DecodeString(sysSessUUID) - uuid = primitive.Binary{Subtype: 0x04, Data: uuidBytes} + uuid = bson.Binary{Subtype: 0x04, Data: uuidBytes} } dbDoc := chunksSchema{ - ID: primitive.NewObjectID(), + ID: bson.NewObjectID(), UUID: uuid, - Min: bson.D{{"_id", primitive.MinKey{}}}, - Max: bson.D{{"_id", primitive.MaxKey{}}}, + Min: bson.D{{"_id", bson.MinKey{}}}, + Max: bson.D{{"_id", bson.MaxKey{}}}, Shard: "rs1", - Lastmod: primitive.Timestamp{T: uint32(i), I: 0}, - OnCurrentShardSince: primitive.Timestamp{T: uint32(time.Now().Unix()), I: 15}, + Lastmod: bson.Timestamp{T: uint32(i), I: 0}, + OnCurrentShardSince: bson.Timestamp{T: uint32(time.Now().Unix()), I: 15}, History: []historyEntry{ { - ValidAfter: primitive.Timestamp{T: uint32(time.Now().Unix()), I: 15}, + ValidAfter: bson.Timestamp{T: uint32(time.Now().Unix()), I: 15}, Shard: "rs1", }, }, diff --git a/pbm/restore/logical_test.go b/pbm/restore/logical_test.go index 4b000ccb9..fe976d252 100644 --- a/pbm/restore/logical_test.go +++ b/pbm/restore/logical_test.go @@ -8,8 +8,7 @@ import ( "strings" "testing" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/backup" "github.com/percona/percona-backup-mongodb/pbm/config" @@ -793,8 +792,8 @@ func createConfigDatabasesDoc(t *testing.T, dbName, primaryShard string) error { {"_id", dbName}, {"primary", primaryShard}, {"version", bson.D{ - {"uuid", primitive.Binary{Subtype: 0x04, Data: []byte("test-uuid")}}, - {"timestamp", primitive.Timestamp{T: 1, I: 0}}, + {"uuid", bson.Binary{Subtype: 0x04, Data: []byte("test-uuid")}}, + {"timestamp", bson.Timestamp{T: 1, I: 0}}, {"lastMod", int64(1)}, }}, } diff --git a/pbm/restore/phys/phys.go b/pbm/restore/phys/phys.go index 8b2135674..6426da71e 100644 --- a/pbm/restore/phys/phys.go +++ b/pbm/restore/phys/phys.go @@ -5,7 +5,7 @@ import ( "fmt" "strconv" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/errors" "github.com/percona/percona-backup-mongodb/pbm/storage" @@ -49,9 +49,9 @@ const ( ) type RestoreTxn struct { - ID string `bson:"id" json:"id"` - Ctime primitive.Timestamp `bson:"ts" json:"ts"` // commit timestamp of the transaction - State TxnState `bson:"state" json:"state"` + ID string `bson:"id" json:"id"` + Ctime bson.Timestamp `bson:"ts" json:"ts"` // commit timestamp of the transaction + State TxnState `bson:"state" json:"state"` } func (t RestoreTxn) Encode() []byte { @@ -73,7 +73,7 @@ func (t *RestoreTxn) Decode(b []byte) error { return errors.Wrap(err, "parse clusterTime I") } - t.Ctime = primitive.Timestamp{T: uint32(tt), I: uint32(ti)} + t.Ctime = bson.Timestamp{T: uint32(tt), I: uint32(ti)} } case 2: t.ID = string(v) diff --git a/pbm/restore/physical.go b/pbm/restore/physical.go index c579fceed..660771eab 100644 --- a/pbm/restore/physical.go +++ b/pbm/restore/physical.go @@ -22,11 +22,10 @@ import ( "time" "github.com/mongodb/mongo-tools/common/db" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" - "go.mongodb.org/mongo-driver/mongo/writeconcern" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" + "go.mongodb.org/mongo-driver/v2/mongo/writeconcern" "golang.org/x/mod/semver" "gopkg.in/yaml.v2" @@ -100,7 +99,7 @@ type PhysRestore struct { bcp *backup.BackupMeta files []files bcpSizeRS int64 // total uncompressed size of the backup for RS (including all increments) - restoreTS primitive.Timestamp + restoreTS bson.Timestamp confOpts *config.RestoreConf @@ -615,7 +614,7 @@ func (r *PhysRestore) checkShutdownFails(ctx context.Context) error { func nodeShutdown(ctx context.Context, m *mongo.Client) error { err := m.Database("admin").RunCommand(ctx, bson.D{{"shutdown", 1}}).Err() - if err == nil || strings.Contains(err.Error(), "socket was unexpectedly closed") { + if err == nil || strings.Contains(err.Error(), "connection closed unexpectedly by the other side") { return nil } return err @@ -846,33 +845,33 @@ func (r *PhysRestore) toState(status defs.Status) (_ defs.Status, err error) { return cstat, nil } -func (r *PhysRestore) getTSFromSyncFile(path string) (primitive.Timestamp, error) { +func (r *PhysRestore) getTSFromSyncFile(path string) (bson.Timestamp, error) { res, err := r.stg.SourceReader(path + "." + string(defs.StatusExtTS)) if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "get timestamp") + return bson.Timestamp{}, errors.Wrap(err, "get timestamp") } b, err := io.ReadAll(res) if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "read timestamp") + return bson.Timestamp{}, errors.Wrap(err, "read timestamp") } tsb := bytes.Split(b, []byte(":")) if len(tsb) != 2 { - return primitive.Timestamp{}, errors.Errorf("wrong file format: %s", tsb) + return bson.Timestamp{}, errors.Errorf("wrong file format: %s", tsb) } tsparts := bytes.Split(tsb[1], []byte(",")) if len(tsparts) != 2 { - return primitive.Timestamp{}, errors.Errorf("wrong timestamp format: %s", tsparts) + return bson.Timestamp{}, errors.Errorf("wrong timestamp format: %s", tsparts) } ctsT, err := strconv.Atoi(string(tsparts[0])) if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "parse ts.T") + return bson.Timestamp{}, errors.Wrap(err, "parse ts.T") } ctsI, err := strconv.Atoi(string(tsparts[1])) if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "parse ts.I") + return bson.Timestamp{}, errors.Wrap(err, "parse ts.I") } - return primitive.Timestamp{ + return bson.Timestamp{ T: uint32(ctsT), I: uint32(ctsI), }, nil @@ -1166,7 +1165,7 @@ func (r *PhysRestore) enableLogBuffWithOrdinal(logger log.Logger, ordinal int) { func (r *PhysRestore) Snapshot( ctx context.Context, cmd *ctrl.RestoreCmd, - pitr primitive.Timestamp, + pitr bson.Timestamp, opid ctrl.OPID, l log.LogEvent, stopAgentC chan<- struct{}, @@ -1438,7 +1437,7 @@ func (r *PhysRestore) prepareExtRestore(l log.LogEvent) (*topo.MongodOpts, error // It uses a few mongod restarts during that process. func (r *PhysRestore) patchSysData( l log.LogEvent, - pitr primitive.Timestamp, + pitr bson.Timestamp, oplogRanges []oplogRange, stats *phys.RestoreShardStat, ) error { @@ -1476,7 +1475,7 @@ func (r *PhysRestore) patchSysData( func (r *PhysRestore) patchSysDataExt(l log.LogEvent) error { return r.patchSysData( l, - primitive.Timestamp{}, + bson.Timestamp{}, nil, &phys.RestoreShardStat{}, ) @@ -1674,16 +1673,16 @@ func (r *PhysRestore) copyFiles() (*storage.DownloadStat, error) { return stat, nil } -func (r *PhysRestore) getLasOpTime() (primitive.Timestamp, error) { +func (r *PhysRestore) getLasOpTime() (bson.Timestamp, error) { err := r.startMongo("--dbpath", r.dbpath, "--setParameter", "disableLogicalSessionCacheRefresh=true") if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "start mongo") + return bson.Timestamp{}, errors.Wrap(err, "start mongo") } c, err := tryConn(r.tmpPort, path.Join(r.dbpath, internalMongodLog)) if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "connect to mongo") + return bson.Timestamp{}, errors.Wrap(err, "connect to mongo") } ctx := context.TODO() @@ -1694,13 +1693,13 @@ func (r *PhysRestore) getLasOpTime() (primitive.Timestamp, error) { options.FindOne().SetSort(bson.D{{"ts", -1}}), ) if res.Err() != nil { - return primitive.Timestamp{}, errors.Wrap(res.Err(), "get oplog entry") + return bson.Timestamp{}, errors.Wrap(res.Err(), "get oplog entry") } rb, err := res.Raw() if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "decode oplog entry") + return bson.Timestamp{}, errors.Wrap(err, "decode oplog entry") } - ts := primitive.Timestamp{} + ts := bson.Timestamp{} var ok bool ts.T, ts.I, ok = rb.Lookup("ts").TimestampOK() if !ok { @@ -1742,8 +1741,9 @@ func (r *PhysRestore) prepareData() error { return errors.Wrap(err, "delete from system.replset") } - _, err = c.Database("local").Collection("replset.minvalid").InsertOne(ctx, - bson.M{"_id": primitive.NewObjectID(), "t": -1, "ts": primitive.Timestamp{0, 1}}, + _, err = c.Database("local").Collection("replset.minvalid").InsertOne( + ctx, + bson.M{"_id": bson.NewObjectID(), "t": -1, "ts": bson.Timestamp{0, 1}}, ) if err != nil { return errors.Wrap(err, "insert to replset.minvalid") @@ -1779,7 +1779,7 @@ func shutdownImpl(c *mongo.Client, dbpath string, force bool, port int) error { res := c.Database("admin").RunCommand(context.TODO(), bson.D{{"shutdown", 1}, {"force", force}}) err := res.Err() - if err != nil && !strings.Contains(err.Error(), "socket was unexpectedly closed") { + if err != nil && !strings.Contains(err.Error(), "connection closed unexpectedly by the other side") { return errors.Wrapf(err, "run shutdown (force: %v)", force) } @@ -1812,8 +1812,8 @@ func (r *PhysRestore) recoverStandaloneFromOplog() error { } func (r *PhysRestore) replayPITROnStandalone( - from primitive.Timestamp, - to primitive.Timestamp, + from bson.Timestamp, + to bson.Timestamp, oplogRanges []oplogRange, stat *phys.RestoreShardStat, ) error { @@ -2086,8 +2086,8 @@ func (r *PhysRestore) getShardMapping(bcp *backup.BackupMeta) map[string]string // pick the oldest ts and put it as the reples ts. And the cluster will // pick the oldest ts proposed by replsets. All comms done via storage. Similar // to the restore states with proposed ts in *.lastTS files. -func (r *PhysRestore) agreeCommonRestoreTS() (primitive.Timestamp, error) { - var ts primitive.Timestamp +func (r *PhysRestore) agreeCommonRestoreTS() (bson.Timestamp, error) { + var ts bson.Timestamp cts, err := r.getLasOpTime() if err != nil { return ts, errors.Wrap(err, "define last op time") @@ -2107,7 +2107,7 @@ func (r *PhysRestore) agreeCommonRestoreTS() (primitive.Timestamp, error) { if err != nil { return ts, errors.Wrap(err, "wait for shards timestamp") } - var mints primitive.Timestamp + var mints bson.Timestamp for sh := range r.syncPathShards { ts, err := r.getTSFromSyncFile(sh) if err != nil { @@ -2151,9 +2151,9 @@ func (r *PhysRestore) setcommittedTxn(_ context.Context, txn []phys.RestoreTxn) return storage.RetryableWrite(r.stg, r.syncPathRS+".txn", b) } -func (r *PhysRestore) getcommittedTxn(context.Context) (map[string]primitive.Timestamp, error) { +func (r *PhysRestore) getcommittedTxn(context.Context) (map[string]bson.Timestamp, error) { shards := maps.Clone(r.syncPathShards) - txn := make(map[string]primitive.Timestamp) + txn := make(map[string]bson.Timestamp) for len(shards) > 0 { for f := range shards { dr, err := r.stg.FileStat(f + "." + string(defs.StatusDone)) @@ -2967,7 +2967,7 @@ type extDump struct { Name string Opid string NodeInfo *topo.NodeInfo - RestoreTS primitive.Timestamp + RestoreTS bson.Timestamp ConfOpts *config.RestoreConf Mongod string diff --git a/pbm/restore/query.go b/pbm/restore/query.go index 4703f6701..e378c8093 100644 --- a/pbm/restore/query.go +++ b/pbm/restore/query.go @@ -6,11 +6,10 @@ import ( "time" "github.com/mongodb/mongo-tools/common/db" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" - "go.mongodb.org/mongo-driver/mongo/writeconcern" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" + "go.mongodb.org/mongo-driver/v2/mongo/writeconcern" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/defs" @@ -137,7 +136,7 @@ func RestoreSetRSPartTxn(ctx context.Context, m connect.Client, name, rsName str return err } -func SetCurrentOp(ctx context.Context, m connect.Client, name, rsName string, ts primitive.Timestamp) error { +func SetCurrentOp(ctx context.Context, m connect.Client, name, rsName string, ts bson.Timestamp) error { _, err := m.RestoresCollection().UpdateOne( ctx, bson.D{{"name", name}, {"replsets.name", rsName}}, @@ -169,7 +168,7 @@ func SetRestoreMetaIfNotExists(ctx context.Context, m connect.Client, meta *Rest _, err := m.RestoresCollection().UpdateOne(ctx, bson.D{{"name", meta.Name}}, bson.D{{"$set", meta}}, - options.Update().SetUpsert(true)) + options.UpdateOne().SetUpsert(true)) return err } @@ -288,7 +287,7 @@ func (d *mDB) runCmdShardsvrDropDatabase( cmd := bson.D{ {"_shardsvrDropDatabase", 1}, {"databaseVersion", configDBDoc.Version}, - {"writeConcern", writeconcern.Majority()}, + {"writeConcern", bson.D{{"w", writeconcern.WCMajority}}}, } res := d.nodeConn.Database(db).RunCommand(ctx, cmd) return errors.Wrapf(res.Err(), "_shardsvrDropDatabase for %q", db) @@ -306,7 +305,7 @@ func (d *mDB) runCmdShardsvrDropCollection( cmd := bson.D{ {"_shardsvrDropCollection", coll}, {"databaseVersion", configDBDoc.Version}, - {"writeConcern", writeconcern.Majority()}, + {"writeConcern", bson.D{{"w", writeconcern.WCMajority}}}, } res := d.nodeConn.Database(db).RunCommand(ctx, cmd) return errors.Wrapf( diff --git a/pbm/restore/restore.go b/pbm/restore/restore.go index 709a8439d..171e64e4a 100644 --- a/pbm/restore/restore.go +++ b/pbm/restore/restore.go @@ -7,8 +7,8 @@ import ( "github.com/golang/snappy" "github.com/mongodb/mongo-tools/common/idx" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/backup" "github.com/percona/percona-backup-mongodb/pbm/compress" @@ -246,7 +246,7 @@ func chunks( conn connect.Client, stg storage.Storage, from, - to primitive.Timestamp, + to bson.Timestamp, rsName string, rsMap map[string]string, ) ([]oplog.OplogChunk, error) { @@ -287,8 +287,8 @@ func chunks( } type applyOplogOption struct { - start *primitive.Timestamp - end *primitive.Timestamp + start *bson.Timestamp + end *bson.Timestamp nss []string cloudNS snapshot.CloneNS unsafe bool @@ -298,7 +298,7 @@ type applyOplogOption struct { type ( setcommittedTxnFn func(ctx context.Context, txn []phys.RestoreTxn) error - getcommittedTxnFn func(ctx context.Context) (map[string]primitive.Timestamp, error) + getcommittedTxnFn func(ctx context.Context) (map[string]bson.Timestamp, error) ) // By looking at just transactions in the oplog we can't tell which shards @@ -347,7 +347,7 @@ func applyOplog( oplogRestore.SetUnsafeMode(options.unsafe) oplogRestore.SetSelectiveUsersAndRolesRestore(options.usersAndRoles) - var startTS, endTS primitive.Timestamp + var startTS, endTS bson.Timestamp if options.start != nil { startTS = *options.start } @@ -365,7 +365,7 @@ func applyOplog( } oplogRestore.SetSessionsToExclude(options.sessUUID) - var lts primitive.Timestamp + var lts bson.Timestamp for _, oplogRange := range ranges { stg := oplogRange.storage for _, chnk := range oplogRange.chunks { @@ -428,17 +428,17 @@ func replayChunk( oplog *oplog.OplogRestore, stg storage.Storage, c compress.CompressionType, -) (primitive.Timestamp, error) { +) (bson.Timestamp, error) { or, err := stg.SourceReader(file) if err != nil { - lts := primitive.Timestamp{} + lts := bson.Timestamp{} return lts, errors.Wrapf(err, "get object %s form the storage", file) } defer or.Close() oplogReader, err := compress.Decompress(or, c) if err != nil { - lts := primitive.Timestamp{} + lts := bson.Timestamp{} return lts, errors.Wrapf(err, "decompress object %s", file) } defer oplogReader.Close() diff --git a/pbm/restore/selective.go b/pbm/restore/selective.go index de2b1b5c1..3bd7e55a9 100644 --- a/pbm/restore/selective.go +++ b/pbm/restore/selective.go @@ -6,8 +6,8 @@ import ( "path" "strings" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/archive" "github.com/percona/percona-backup-mongodb/pbm/backup" diff --git a/pbm/restore/storage.go b/pbm/restore/storage.go index 2308bf081..72ef436a6 100644 --- a/pbm/restore/storage.go +++ b/pbm/restore/storage.go @@ -12,7 +12,7 @@ import ( "time" "github.com/mongodb/mongo-tools/common/db" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "gopkg.in/yaml.v2" "github.com/percona/percona-backup-mongodb/pbm/config" @@ -342,6 +342,6 @@ func GetRestoreMetaStg(cfgPath, node string) (storage.Storage, error) { return nil, errors.Wrap(err, "unable to unmarshal config file") } - l := log.New(nil, "cli", "").NewEvent("", "", "", primitive.Timestamp{}) + l := log.New(nil, "cli", "").NewEvent("", "", "", bson.Timestamp{}) return util.StorageFromConfig(&cfg.Storage, node, l) } diff --git a/pbm/restore/types.go b/pbm/restore/types.go index 7031f47d8..65740141c 100644 --- a/pbm/restore/types.go +++ b/pbm/restore/types.go @@ -4,30 +4,30 @@ import ( "sort" "github.com/mongodb/mongo-tools/common/db" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/defs" "github.com/percona/percona-backup-mongodb/pbm/restore/phys" ) type RestoreMeta struct { - Status defs.Status `bson:"status" json:"status"` - Error string `bson:"error,omitempty" json:"error,omitempty"` - Name string `bson:"name" json:"name"` - OPID string `bson:"opid" json:"opid"` - Backup string `bson:"backup" json:"backup"` - BcpChain []string `bson:"bcp_chain" json:"bcp_chain"` // for incremental - Namespaces []string `bson:"nss,omitempty" json:"nss,omitempty"` - StartPITR int64 `bson:"start_pitr" json:"start_pitr"` - PITR int64 `bson:"pitr" json:"pitr"` - Replsets []RestoreReplset `bson:"replsets" json:"replsets"` - Hb primitive.Timestamp `bson:"hb" json:"hb"` - StartTS int64 `bson:"start_ts" json:"start_ts"` - LastTransitionTS int64 `bson:"last_transition_ts" json:"last_transition_ts"` - Conditions Conditions `bson:"conditions" json:"conditions"` - Type defs.BackupType `bson:"type" json:"type"` - Leader string `bson:"l,omitempty" json:"l,omitempty"` - Stat *phys.RestoreStat `bson:"stat,omitempty" json:"stat,omitempty"` + Status defs.Status `bson:"status" json:"status"` + Error string `bson:"error,omitempty" json:"error,omitempty"` + Name string `bson:"name" json:"name"` + OPID string `bson:"opid" json:"opid"` + Backup string `bson:"backup" json:"backup"` + BcpChain []string `bson:"bcp_chain" json:"bcp_chain"` // for incremental + Namespaces []string `bson:"nss,omitempty" json:"nss,omitempty"` + StartPITR int64 `bson:"start_pitr" json:"start_pitr"` + PITR int64 `bson:"pitr" json:"pitr"` + Replsets []RestoreReplset `bson:"replsets" json:"replsets"` + Hb bson.Timestamp `bson:"hb" json:"hb"` + StartTS int64 `bson:"start_ts" json:"start_ts"` + LastTransitionTS int64 `bson:"last_transition_ts" json:"last_transition_ts"` + Conditions Conditions `bson:"conditions" json:"conditions"` + Type defs.BackupType `bson:"type" json:"type"` + Leader string `bson:"l,omitempty" json:"l,omitempty"` + Stat *phys.RestoreStat `bson:"stat,omitempty" json:"stat,omitempty"` } type RestoreReplset struct { @@ -37,13 +37,13 @@ type RestoreReplset struct { CommittedTxn []phys.RestoreTxn `bson:"committed_txn" json:"committed_txn"` CommittedTxnSet bool `bson:"txn_set" json:"txn_set"` PartialTxn []db.Oplog `bson:"partial_txn" json:"partial_txn"` - CurrentOp primitive.Timestamp `bson:"op" json:"op"` + CurrentOp bson.Timestamp `bson:"op" json:"op"` LastTransitionTS int64 `bson:"last_transition_ts" json:"last_transition_ts"` - LastWriteTS primitive.Timestamp `bson:"last_write_ts" json:"last_write_ts"` + LastWriteTS bson.Timestamp `bson:"last_write_ts" json:"last_write_ts"` Nodes []RestoreNode `bson:"nodes,omitempty" json:"nodes,omitempty"` Error string `bson:"error,omitempty" json:"error,omitempty"` Conditions Conditions `bson:"conditions" json:"conditions"` - Hb primitive.Timestamp `bson:"hb" json:"hb"` + Hb bson.Timestamp `bson:"hb" json:"hb"` Stat phys.RestoreShardStat `bson:"stat" json:"stat"` } @@ -68,10 +68,10 @@ func (b *Conditions) Insert(c *Condition) { } type RestoreNode struct { - Name string `bson:"name" json:"name"` - Status defs.Status `bson:"status" json:"status"` - LastTransitionTS int64 `bson:"last_transition_ts" json:"last_transition_ts"` - Error string `bson:"error,omitempty" json:"error,omitempty"` - Conditions Conditions `bson:"conditions" json:"conditions"` - Hb primitive.Timestamp `bson:"hb" json:"hb"` + Name string `bson:"name" json:"name"` + Status defs.Status `bson:"status" json:"status"` + LastTransitionTS int64 `bson:"last_transition_ts" json:"last_transition_ts"` + Error string `bson:"error,omitempty" json:"error,omitempty"` + Conditions Conditions `bson:"conditions" json:"conditions"` + Hb bson.Timestamp `bson:"hb" json:"hb"` } diff --git a/pbm/resync/rsync.go b/pbm/resync/rsync.go index 9caa83ce1..076fc6e7b 100644 --- a/pbm/resync/rsync.go +++ b/pbm/resync/rsync.go @@ -6,9 +6,9 @@ import ( "strings" "sync" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" "github.com/percona/percona-backup-mongodb/pbm/backup" "github.com/percona/percona-backup-mongodb/pbm/config" diff --git a/pbm/slicer/slicer.go b/pbm/slicer/slicer.go index 052c485d0..e15c15235 100644 --- a/pbm/slicer/slicer.go +++ b/pbm/slicer/slicer.go @@ -6,8 +6,8 @@ import ( "sync/atomic" "time" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/backup" "github.com/percona/percona-backup-mongodb/pbm/compress" @@ -34,7 +34,7 @@ type Slicer struct { node *mongo.Client rs string span int64 - lastTS primitive.Timestamp + lastTS bson.Timestamp storage storage.Storage oplog *oplog.OplogBackup l log.LogEvent @@ -333,7 +333,7 @@ func (s *Slicer) Stream( } for { - sliceTo := primitive.Timestamp{} + sliceTo := bson.Timestamp{} // waiting for a trigger select { // wrapping up at the current point-in-time @@ -371,7 +371,7 @@ func (s *Slicer) Stream( s.l.Info("unsuitable backup [opid: %q]", opid) s.l.Info("pausing/stopping with last_ts %v", time.Unix(int64(s.lastTS.T), 0).UTC()) - sliceTo = primitive.Timestamp{} + sliceTo = bson.Timestamp{} } else if s.lastTS.After(sliceTo) { // it can happen that prevoius slice >= backup's fisrt_write // in that case we have to just back off. @@ -474,8 +474,8 @@ func (s *Slicer) Stream( func (s *Slicer) upload( ctx context.Context, - from primitive.Timestamp, - to primitive.Timestamp, + from bson.Timestamp, + to bson.Timestamp, compression compress.CompressionType, level *int, ) error { @@ -531,7 +531,7 @@ func (s *Slicer) deleteLastChunk(ctx context.Context) error { return nil } -func formatts(t primitive.Timestamp) string { +func formatts(t bson.Timestamp) string { return time.Unix(int64(t.T), 0).UTC().Format("2006-01-02T15:04:05") } @@ -557,8 +557,8 @@ func (s *Slicer) getOpLock(ctx context.Context, l *lock.LockHeader, t time.Durat var errUnsuitableBackup = errors.New("unsuitable backup") -func (s *Slicer) backupRSStartTS(ctx context.Context, opid string, t time.Duration) (primitive.Timestamp, error) { - var ts primitive.Timestamp +func (s *Slicer) backupRSStartTS(ctx context.Context, opid string, t time.Duration) (bson.Timestamp, error) { + var ts bson.Timestamp tk := time.NewTicker(time.Second) defer tk.Stop() diff --git a/pbm/slicer/slicer_test.go b/pbm/slicer/slicer_test.go index 68a614ec2..3665a32ab 100644 --- a/pbm/slicer/slicer_test.go +++ b/pbm/slicer/slicer_test.go @@ -11,10 +11,9 @@ import ( "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/mongodb" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" "github.com/percona/percona-backup-mongodb/pbm/backup" "github.com/percona/percona-backup-mongodb/pbm/compress" @@ -43,7 +42,7 @@ func TestMain(m *testing.M) { if err != nil { log.Fatalf("conn string error: %v", err) } - mClient, err = mongo.Connect(ctx, options.Client().ApplyURI(connStr)) + mClient, err = mongo.Connect(options.Client().ApplyURI(connStr)) if err != nil { log.Fatalf("mongo client connect error: %v", err) } @@ -86,8 +85,8 @@ func TestCatchup(t *testing.T) { backupMeta.Replsets = []backup.BackupReplset{ { Name: "rsX", - FirstWriteTS: primitive.Timestamp{T: 500, I: 0}, - LastWriteTS: primitive.Timestamp{T: 1000, I: 0}, + FirstWriteTS: bson.Timestamp{T: 500, I: 0}, + LastWriteTS: bson.Timestamp{T: 1000, I: 0}, }, } _, err := connClient.BcpCollection().InsertOne(ctx, backupMeta) @@ -107,7 +106,7 @@ func TestCatchup(t *testing.T) { t.Run("no existing PITR chunks, use last write from backup", func(t *testing.T) { s := createTestSlicer(t) - wantLastTS := primitive.Timestamp{T: 1000, I: 0} + wantLastTS := bson.Timestamp{T: 1000, I: 0} backupMeta := createBackupMeta() backupMeta.LastWriteTS = wantLastTS backupMeta.Replsets[0].LastWriteTS = wantLastTS @@ -130,8 +129,8 @@ func TestCatchup(t *testing.T) { backupMeta := createBackupMeta() backupMeta.StartTS = 1000 - backupMeta.LastWriteTS = primitive.Timestamp{T: 1000, I: 0} - backupMeta.Replsets[0].LastWriteTS = primitive.Timestamp{T: 1000, I: 0} + backupMeta.LastWriteTS = bson.Timestamp{T: 1000, I: 0} + backupMeta.Replsets[0].LastWriteTS = bson.Timestamp{T: 1000, I: 0} _, err := connClient.BcpCollection().InsertOne(ctx, backupMeta) if err != nil { t.Fatalf("failed to insert backup: %v", err) @@ -161,7 +160,7 @@ func TestCatchup(t *testing.T) { t.Run("chunk after backup", func(t *testing.T) { s := createTestSlicer(t) - lastWriteTS := primitive.Timestamp{T: 1000, I: 0} + lastWriteTS := bson.Timestamp{T: 1000, I: 0} backupMeta := createBackupMeta() backupMeta.LastWriteTS = lastWriteTS backupMeta.Replsets[0].LastWriteTS = lastWriteTS @@ -170,12 +169,12 @@ func TestCatchup(t *testing.T) { t.Fatalf("failed to insert backup: %v", err) } - wantChunkEndTS := primitive.Timestamp{T: 1500, I: 0} + wantChunkEndTS := bson.Timestamp{T: 1500, I: 0} chunk := &oplog.OplogChunk{ RS: "rs0", FName: "chunk1", Compression: compress.CompressionTypeNone, - StartTS: primitive.Timestamp{T: 1000, I: 0}, + StartTS: bson.Timestamp{T: 1000, I: 0}, EndTS: wantChunkEndTS, Size: 1024, } @@ -196,7 +195,7 @@ func TestCatchup(t *testing.T) { t.Run("restore after last chunk", func(t *testing.T) { s := createTestSlicer(t) - wantLastTS := primitive.Timestamp{T: 1000, I: 0} + wantLastTS := bson.Timestamp{T: 1000, I: 0} backupMeta := createBackupMeta() backupMeta.LastWriteTS = wantLastTS backupMeta.Replsets[0].LastWriteTS = wantLastTS @@ -205,12 +204,12 @@ func TestCatchup(t *testing.T) { t.Fatalf("failed to insert backup: %v", err) } - chunkEndTS := primitive.Timestamp{T: 800, I: 0} + chunkEndTS := bson.Timestamp{T: 800, I: 0} chunk := &oplog.OplogChunk{ RS: "rs0", FName: "chunk1", Compression: compress.CompressionTypeNone, - StartTS: primitive.Timestamp{T: 500, I: 0}, + StartTS: bson.Timestamp{T: 500, I: 0}, EndTS: chunkEndTS, Size: 1024, } @@ -244,8 +243,8 @@ func TestCatchup(t *testing.T) { t.Run("chunk between backup timestamps", func(t *testing.T) { s := createTestSlicer(t) - backupFirstTS := primitive.Timestamp{T: 500, I: 0} - wantLastTS := primitive.Timestamp{T: 1000, I: 0} + backupFirstTS := bson.Timestamp{T: 500, I: 0} + wantLastTS := bson.Timestamp{T: 1000, I: 0} backupMeta := createBackupMeta() backupMeta.LastWriteTS = wantLastTS backupMeta.Replsets[0].FirstWriteTS = backupFirstTS @@ -258,12 +257,12 @@ func TestCatchup(t *testing.T) { createPITRFilesOnStorage(t, s.storage, backupMeta.Replsets[0].OplogName, backupFirstTS, wantLastTS) // Create a chunk with endTS between backup FirstWriteTS and LastWriteTS - chunkEndTS := primitive.Timestamp{T: 750, I: 0} + chunkEndTS := bson.Timestamp{T: 750, I: 0} chunk := &oplog.OplogChunk{ RS: "rs0", FName: "chunk1", Compression: compress.CompressionTypeNone, - StartTS: primitive.Timestamp{T: 600, I: 0}, + StartTS: bson.Timestamp{T: 600, I: 0}, EndTS: chunkEndTS, Size: 1024, } @@ -294,8 +293,8 @@ func TestCatchup(t *testing.T) { t.Run("chunk before backup first write", func(t *testing.T) { s := createTestSlicer(t) - backupFirstTS := primitive.Timestamp{T: 1000, I: 0} - backupLastTS := primitive.Timestamp{T: 1500, I: 0} + backupFirstTS := bson.Timestamp{T: 1000, I: 0} + backupLastTS := bson.Timestamp{T: 1500, I: 0} backupMeta := createBackupMeta() backupMeta.LastWriteTS = backupLastTS backupMeta.Replsets[0].FirstWriteTS = backupFirstTS @@ -309,12 +308,12 @@ func TestCatchup(t *testing.T) { createPITRFilesOnStorage(t, s.storage, backupMeta.Replsets[0].OplogName, backupFirstTS, backupLastTS) // Create a chunk with endTS before backup FirstWriteTS - chunkEndTS := primitive.Timestamp{T: 500, I: 0} + chunkEndTS := bson.Timestamp{T: 500, I: 0} chunk := &oplog.OplogChunk{ RS: "rs0", FName: "chunk1", Compression: compress.CompressionTypeNone, - StartTS: primitive.Timestamp{T: 200, I: 0}, + StartTS: bson.Timestamp{T: 200, I: 0}, EndTS: chunkEndTS, Size: 1024, } @@ -346,8 +345,8 @@ func TestCatchup(t *testing.T) { t.Run("logical backup with no PITR files", func(t *testing.T) { s := createTestSlicer(t) - backupFirstTS := primitive.Timestamp{T: 1000, I: 0} - backupLastTS := primitive.Timestamp{T: 1500, I: 0} + backupFirstTS := bson.Timestamp{T: 1000, I: 0} + backupLastTS := bson.Timestamp{T: 1500, I: 0} backupMeta := createBackupMeta() backupMeta.Type = defs.LogicalBackup backupMeta.LastWriteTS = backupLastTS @@ -360,12 +359,12 @@ func TestCatchup(t *testing.T) { t.Fatalf("failed to insert backup: %v", err) } - chunkEndTS := primitive.Timestamp{T: 750, I: 0} + chunkEndTS := bson.Timestamp{T: 750, I: 0} chunk := &oplog.OplogChunk{ RS: "rs0", FName: "chunk1", Compression: compress.CompressionTypeNone, - StartTS: primitive.Timestamp{T: 600, I: 0}, + StartTS: bson.Timestamp{T: 600, I: 0}, EndTS: chunkEndTS, Size: 1024, } @@ -412,7 +411,7 @@ func createTestSlicer(t *testing.T) *Slicer { t.Fatalf("failed to create filesystem storage: %v", err) } cfg := &config.Config{ - Epoch: primitive.Timestamp{T: 1, I: 0}, + Epoch: bson.Timestamp{T: 1, I: 0}, PITR: &config.PITRConf{ Compression: compress.CompressionTypeNone, }, @@ -422,7 +421,7 @@ func createTestSlicer(t *testing.T) *Slicer { } func createBackupMeta() *backup.BackupMeta { - lastWriteTS := primitive.Timestamp{T: 1000, I: 0} + lastWriteTS := bson.Timestamp{T: 1000, I: 0} return &backup.BackupMeta{ Name: "2025-11-21T09:38:09Z", Type: defs.LogicalBackup, @@ -432,7 +431,7 @@ func createBackupMeta() *backup.BackupMeta { Replsets: []backup.BackupReplset{ { Name: "rs0", - FirstWriteTS: primitive.Timestamp{T: 500, I: 0}, + FirstWriteTS: bson.Timestamp{T: 500, I: 0}, LastWriteTS: lastWriteTS, }, }, @@ -463,7 +462,7 @@ func createPITRFilesOnStorage( t *testing.T, stg storage.Storage, oplogPath string, - firstTS, lastTS primitive.Timestamp, + firstTS, lastTS bson.Timestamp, ) { t.Helper() diff --git a/pbm/snapshot/restore.go b/pbm/snapshot/restore.go index 1617be46a..2d1173516 100644 --- a/pbm/snapshot/restore.go +++ b/pbm/snapshot/restore.go @@ -7,8 +7,8 @@ import ( "strings" "github.com/mongodb/mongo-tools/common/options" + "github.com/mongodb/mongo-tools/common/wcwrapper" "github.com/mongodb/mongo-tools/mongorestore" - "go.mongodb.org/mongo-driver/mongo/writeconcern" "github.com/percona/percona-backup-mongodb/pbm/config" "github.com/percona/percona-backup-mongodb/pbm/defs" @@ -97,7 +97,7 @@ func NewRestore(uri string, } topts.Direct = true - topts.WriteConcern = writeconcern.Majority() + topts.WriteConcern = wcwrapper.Majority() batchSize := batchSizeDefault if cfg.Restore.BatchSize > 0 { diff --git a/pbm/topo/agent.go b/pbm/topo/agent.go index 07a738a17..27383d252 100644 --- a/pbm/topo/agent.go +++ b/pbm/topo/agent.go @@ -5,9 +5,8 @@ import ( "strconv" "strings" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo/options" "golang.org/x/mod/semver" "github.com/percona/percona-backup-mongodb/pbm/connect" @@ -69,7 +68,7 @@ type AgentStat struct { StorageStatus SubsysStatus `bson:"stors"` // Heartbeat is agent's last seen cluster time. - Heartbeat primitive.Timestamp `bson:"hb"` + Heartbeat bson.Timestamp `bson:"hb"` // Err can be any error. Err string `bson:"e"` @@ -85,7 +84,7 @@ type SubsysStatus struct { } // IsStale returns true if agent's heartbeat is steal for the give `t` cluster time. -func (s *AgentStat) IsStale(t primitive.Timestamp) bool { +func (s *AgentStat) IsStale(t bson.Timestamp) bool { return s.Heartbeat.T+defs.StaleFrameSec < t.T } diff --git a/pbm/topo/cluster.go b/pbm/topo/cluster.go index e362632ff..74dff12f1 100644 --- a/pbm/topo/cluster.go +++ b/pbm/topo/cluster.go @@ -4,11 +4,10 @@ import ( "context" "strings" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" - "go.mongodb.org/mongo-driver/mongo/writeconcern" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" + "go.mongodb.org/mongo-driver/v2/mongo/writeconcern" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/errors" @@ -39,46 +38,46 @@ type Shard struct { } // ClusterTime returns mongo's current cluster time -func GetClusterTime(ctx context.Context, m connect.Client) (primitive.Timestamp, error) { +func GetClusterTime(ctx context.Context, m connect.Client) (bson.Timestamp, error) { // Make a read to force the cluster timestamp update. // Otherwise, cluster timestamp could remain the same between node info reads, // while in fact time has been moved forward. err := m.LockCollection().FindOne(ctx, bson.D{}).Err() if err != nil && !errors.Is(err, mongo.ErrNoDocuments) { - return primitive.Timestamp{}, errors.Wrap(err, "void read") + return bson.Timestamp{}, errors.Wrap(err, "void read") } inf, err := GetNodeInfo(ctx, m.MongoClient()) if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "get NodeInfo") + return bson.Timestamp{}, errors.Wrap(err, "get NodeInfo") } return ClusterTimeFromNodeInfo(inf) } -func ClusterTimeFromNodeInfo(info *NodeInfo) (primitive.Timestamp, error) { +func ClusterTimeFromNodeInfo(info *NodeInfo) (bson.Timestamp, error) { if info.ClusterTime == nil { - return primitive.Timestamp{}, errors.Errorf("No clusterTime in response. Received: %+v", info) + return bson.Timestamp{}, errors.Errorf("No clusterTime in response. Received: %+v", info) } return info.ClusterTime.ClusterTime, nil } -func GetLastWrite(ctx context.Context, m *mongo.Client, majority bool) (primitive.Timestamp, error) { +func GetLastWrite(ctx context.Context, m *mongo.Client, majority bool) (bson.Timestamp, error) { inf, err := GetNodeInfo(ctx, m) if err != nil { - return primitive.Timestamp{}, errors.Wrap(err, "get NodeInfo data") + return bson.Timestamp{}, errors.Wrap(err, "get NodeInfo data") } return OpTimeFromNodeInfo(inf, majority) } -func OpTimeFromNodeInfo(inf *NodeInfo, majority bool) (primitive.Timestamp, error) { +func OpTimeFromNodeInfo(inf *NodeInfo, majority bool) (bson.Timestamp, error) { lw := inf.LastWrite.MajorityOpTime.TS if !majority { lw = inf.LastWrite.OpTime.TS } if lw.T == 0 { - return primitive.Timestamp{}, errors.New("last write timestamp is nil") + return bson.Timestamp{}, errors.New("last write timestamp is nil") } return lw, nil } @@ -92,7 +91,7 @@ func IsWriteMajorityRequested( ) (bool, error) { if writeConcern == nil || !writeConcern.IsValid() || - writeConcern == writeconcern.Majority() { + *writeConcern == *writeconcern.Majority() { return true, nil } diff --git a/pbm/topo/node.go b/pbm/topo/node.go index 38ca5715d..9202d438d 100644 --- a/pbm/topo/node.go +++ b/pbm/topo/node.go @@ -5,9 +5,8 @@ import ( "strconv" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/defs" "github.com/percona/percona-backup-mongodb/pbm/errors" @@ -35,8 +34,8 @@ const ( ) type OpTime struct { - TS primitive.Timestamp `bson:"ts" json:"ts"` - Term int64 `bson:"t" json:"t"` + TS bson.Timestamp `bson:"ts" json:"ts"` + Term int64 `bson:"t" json:"t"` } // MongoLastWrite represents the last write to the MongoDB server @@ -48,10 +47,10 @@ type MongoLastWrite struct { } type ClusterTime struct { - ClusterTime primitive.Timestamp `bson:"clusterTime"` + ClusterTime bson.Timestamp `bson:"clusterTime"` Signature struct { - Hash primitive.Binary `bson:"hash"` - KeyID int64 `bson:"keyId"` + Hash bson.Binary `bson:"hash"` + KeyID int64 `bson:"keyId"` } `bson:"signature"` } @@ -70,33 +69,33 @@ type NodeBrief struct { // NodeInfo represents the mongo's node info type NodeInfo struct { - Hosts []string `bson:"hosts,omitempty"` - Msg string `bson:"msg"` - MaxBsonObjectSise int64 `bson:"maxBsonObjectSize"` - MaxMessageSizeBytes int64 `bson:"maxMessageSizeBytes"` - MaxWriteBatchSize int64 `bson:"maxWriteBatchSize"` - LocalTime time.Time `bson:"localTime"` - LogicalSessionTimeoutMinutes int64 `bson:"logicalSessionTimeoutMinutes"` - MaxWireVersion int64 `bson:"maxWireVersion"` - MinWireVersion int64 `bson:"minWireVersion"` - OK int `bson:"ok"` - SetName string `bson:"setName,omitempty"` - Primary string `bson:"primary,omitempty"` - SetVersion int32 `bson:"setVersion,omitempty"` - IsPrimary bool `bson:"isWritablePrimary"` - Secondary bool `bson:"secondary,omitempty"` - Hidden bool `bson:"hidden,omitempty"` - Passive bool `bson:"passive,omitempty"` - ArbiterOnly bool `bson:"arbiterOnly"` - SecondaryDelayOld int32 `bson:"slaveDelay"` - SecondaryDelaySecs int32 `bson:"secondaryDelaySecs"` - ConfigSvr int `bson:"configsvr,omitempty"` - Me string `bson:"me"` - LastWrite MongoLastWrite `bson:"lastWrite"` - ClusterTime *ClusterTime `bson:"$clusterTime,omitempty"` - ConfigServerState *ConfigServerState `bson:"$configServerState,omitempty"` - OperationTime *primitive.Timestamp `bson:"operationTime,omitempty"` - Opts MongodOpts `bson:"-"` + Hosts []string `bson:"hosts,omitempty"` + Msg string `bson:"msg"` + MaxBsonObjectSise int64 `bson:"maxBsonObjectSize"` + MaxMessageSizeBytes int64 `bson:"maxMessageSizeBytes"` + MaxWriteBatchSize int64 `bson:"maxWriteBatchSize"` + LocalTime time.Time `bson:"localTime"` + LogicalSessionTimeoutMinutes int64 `bson:"logicalSessionTimeoutMinutes"` + MaxWireVersion int64 `bson:"maxWireVersion"` + MinWireVersion int64 `bson:"minWireVersion"` + OK int `bson:"ok"` + SetName string `bson:"setName,omitempty"` + Primary string `bson:"primary,omitempty"` + SetVersion int32 `bson:"setVersion,omitempty"` + IsPrimary bool `bson:"isWritablePrimary"` + Secondary bool `bson:"secondary,omitempty"` + Hidden bool `bson:"hidden,omitempty"` + Passive bool `bson:"passive,omitempty"` + ArbiterOnly bool `bson:"arbiterOnly"` + SecondaryDelayOld int32 `bson:"slaveDelay"` + SecondaryDelaySecs int32 `bson:"secondaryDelaySecs"` + ConfigSvr int `bson:"configsvr,omitempty"` + Me string `bson:"me"` + LastWrite MongoLastWrite `bson:"lastWrite"` + ClusterTime *ClusterTime `bson:"$clusterTime,omitempty"` + ConfigServerState *ConfigServerState `bson:"$configServerState,omitempty"` + OperationTime *bson.Timestamp `bson:"operationTime,omitempty"` + Opts MongodOpts `bson:"-"` } func (i *NodeInfo) IsDelayed() bool { diff --git a/pbm/topo/status.go b/pbm/topo/status.go index 4cad00a51..c40e81e5f 100644 --- a/pbm/topo/status.go +++ b/pbm/topo/status.go @@ -4,9 +4,8 @@ import ( "context" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/defs" "github.com/percona/percona-backup-mongodb/pbm/errors" @@ -22,20 +21,20 @@ type NodeStatus struct { // https://github.com/mongodb/mongo/blob/v8.0/src/mongo/db/repl/member_state.h#L170-L193 StateStr string `bson:"stateStr" json:"stateStr"` - Uptime int64 `bson:"uptime" json:"uptime"` - Optime *OpTime `bson:"optime" json:"optime"` - OptimeDate time.Time `bson:"optimeDate" json:"optimeDate"` - ConfigVersion int `bson:"configVersion" json:"configVersion"` - ElectionTime primitive.Timestamp `bson:"electionTime,omitempty" json:"electionTime,omitempty"` - ElectionDate time.Time `bson:"electionDate,omitempty" json:"electionDate,omitempty"` - InfoMessage string `bson:"infoMessage,omitempty" json:"infoMessage,omitempty"` - OptimeDurable *OpTime `bson:"optimeDurable,omitempty" json:"optimeDurable,omitempty"` - OptimeDurableDate time.Time `bson:"optimeDurableDate,omitempty" json:"optimeDurableDate,omitempty"` - LastHeartbeat time.Time `bson:"lastHeartbeat,omitempty" json:"lastHeartbeat,omitempty"` - LastHeartbeatRecv time.Time `bson:"lastHeartbeatRecv,omitempty" json:"lastHeartbeatRecv,omitempty"` - PingMs int64 `bson:"pingMs,omitempty" json:"pingMs,omitempty"` - Self bool `bson:"self,omitempty" json:"self,omitempty"` - SyncingTo string `bson:"syncingTo,omitempty" json:"syncingTo,omitempty"` + Uptime int64 `bson:"uptime" json:"uptime"` + Optime *OpTime `bson:"optime" json:"optime"` + OptimeDate time.Time `bson:"optimeDate" json:"optimeDate"` + ConfigVersion int `bson:"configVersion" json:"configVersion"` + ElectionTime bson.Timestamp `bson:"electionTime,omitempty" json:"electionTime,omitempty"` + ElectionDate time.Time `bson:"electionDate,omitempty" json:"electionDate,omitempty"` + InfoMessage string `bson:"infoMessage,omitempty" json:"infoMessage,omitempty"` + OptimeDurable *OpTime `bson:"optimeDurable,omitempty" json:"optimeDurable,omitempty"` + OptimeDurableDate time.Time `bson:"optimeDurableDate,omitempty" json:"optimeDurableDate,omitempty"` + LastHeartbeat time.Time `bson:"lastHeartbeat,omitempty" json:"lastHeartbeat,omitempty"` + LastHeartbeatRecv time.Time `bson:"lastHeartbeatRecv,omitempty" json:"lastHeartbeatRecv,omitempty"` + PingMs int64 `bson:"pingMs,omitempty" json:"pingMs,omitempty"` + Self bool `bson:"self,omitempty" json:"self,omitempty"` + SyncingTo string `bson:"syncingTo,omitempty" json:"syncingTo,omitempty"` } func (s *NodeStatus) IsArbiter() bool { @@ -50,19 +49,19 @@ type StatusOpTimes struct { } type ReplsetStatus struct { - Set string `bson:"set" json:"set"` - Date time.Time `bson:"date" json:"date"` - MyState defs.NodeState `bson:"myState" json:"myState"` - Members []NodeStatus `bson:"members" json:"members"` - Term int64 `bson:"term,omitempty" json:"term,omitempty"` - HeartbeatIntervalMillis int64 `bson:"heartbeatIntervalMillis,omitempty" json:"heartbeatIntervalMillis,omitempty"` //nolint:lll - Optimes *StatusOpTimes `bson:"optimes,omitempty" json:"optimes,omitempty"` - Errmsg string `bson:"errmsg,omitempty" json:"errmsg,omitempty"` - Ok int `bson:"ok" json:"ok"` - ClusterTime *ClusterTime `bson:"$clusterTime,omitempty" json:"$clusterTime,omitempty"` - ConfigServerState *ConfigServerState `bson:"$configServerState,omitempty" json:"$configServerState,omitempty"` - OperationTime *primitive.Timestamp `bson:"operationTime,omitempty" json:"operationTime,omitempty"` - WriteMajorityCount int `bson:"writeMajorityCount,omitempty" json:"writeMajorityCount,omitempty"` + Set string `bson:"set" json:"set"` + Date time.Time `bson:"date" json:"date"` + MyState defs.NodeState `bson:"myState" json:"myState"` + Members []NodeStatus `bson:"members" json:"members"` + Term int64 `bson:"term,omitempty" json:"term,omitempty"` + HeartbeatIntervalMillis int64 `bson:"heartbeatIntervalMillis,omitempty" json:"heartbeatIntervalMillis,omitempty"` //nolint:lll + Optimes *StatusOpTimes `bson:"optimes,omitempty" json:"optimes,omitempty"` + Errmsg string `bson:"errmsg,omitempty" json:"errmsg,omitempty"` + Ok int `bson:"ok" json:"ok"` + ClusterTime *ClusterTime `bson:"$clusterTime,omitempty" json:"$clusterTime,omitempty"` + ConfigServerState *ConfigServerState `bson:"$configServerState,omitempty" json:"$configServerState,omitempty"` + OperationTime *bson.Timestamp `bson:"operationTime,omitempty" json:"operationTime,omitempty"` + WriteMajorityCount int `bson:"writeMajorityCount,omitempty" json:"writeMajorityCount,omitempty"` } func CurrentUser(ctx context.Context, m *mongo.Client) (*AuthInfo, error) { diff --git a/pbm/topo/topo.go b/pbm/topo/topo.go index bc136cab1..7dba40000 100644 --- a/pbm/topo/topo.go +++ b/pbm/topo/topo.go @@ -6,9 +6,8 @@ import ( "strings" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/connect" "github.com/percona/percona-backup-mongodb/pbm/defs" @@ -89,7 +88,7 @@ func (r topoCheckError) Error() string { func collectTopoCheckErrors( replsets []Shard, agentsByRS map[ReplsetName]map[NodeURI]AgentStat, - ts primitive.Timestamp, + ts bson.Timestamp, type_ defs.BackupType, ) error { rv := topoCheckError{ diff --git a/pbm/util/query.go b/pbm/util/query.go index 7d1e79ba5..e3f388dd3 100644 --- a/pbm/util/query.go +++ b/pbm/util/query.go @@ -3,7 +3,7 @@ package util import ( "context" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/mongo" "github.com/percona/percona-backup-mongodb/pbm/defs" "github.com/percona/percona-backup-mongodb/pbm/errors" diff --git a/pbm/util/sel.go b/pbm/util/sel.go index 621bf524a..23c6577c1 100644 --- a/pbm/util/sel.go +++ b/pbm/util/sel.go @@ -5,9 +5,9 @@ import ( "slices" "strings" + "go.mongodb.org/mongo-driver/v2/bson" + "github.com/percona/percona-backup-mongodb/pbm/errors" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" "github.com/percona/percona-backup-mongodb/pbm/archive" ) @@ -168,10 +168,10 @@ func (s uuidChunkMap) Selected(d bson.Raw) bool { } func (s uuidChunkMap) BuildFilter() bson.D { - uuids := make([]primitive.Binary, 0, len(s)) + uuids := make([]bson.Binary, 0, len(s)) for ns := range s { data, _ := hex.DecodeString(ns) - uuids = append(uuids, primitive.Binary{Subtype: 0x4, Data: data}) + uuids = append(uuids, bson.Binary{Subtype: 0x4, Data: data}) } return bson.D{{"uuid", bson.M{"$in": uuids}}} diff --git a/pbm/version/version.go b/pbm/version/version.go index 7e3bddc5b..8f484f496 100644 --- a/pbm/version/version.go +++ b/pbm/version/version.go @@ -7,8 +7,8 @@ import ( "runtime" "strings" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "golang.org/x/mod/semver" "github.com/percona/percona-backup-mongodb/pbm/defs" diff --git a/sdk/cli/status.go b/sdk/cli/status.go index c62a74119..869f80fc8 100644 --- a/sdk/cli/status.go +++ b/sdk/cli/status.go @@ -7,7 +7,7 @@ import ( "strings" "sync" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "golang.org/x/sync/errgroup" "github.com/percona/percona-backup-mongodb/pbm/connect" @@ -18,7 +18,7 @@ import ( ) type LostAgentError struct { - heartbeat primitive.Timestamp + heartbeat bson.Timestamp } func (e LostAgentError) Error() string { diff --git a/sdk/impl.go b/sdk/impl.go index d42120086..fcf25b044 100644 --- a/sdk/impl.go +++ b/sdk/impl.go @@ -5,8 +5,8 @@ import ( "runtime" "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" "golang.org/x/sync/errgroup" "github.com/percona/percona-backup-mongodb/pbm/backup" diff --git a/sdk/sdk.go b/sdk/sdk.go index be7e60892..d771a3192 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/v2/bson" "github.com/percona/percona-backup-mongodb/pbm/backup" "github.com/percona/percona-backup-mongodb/pbm/compress" @@ -30,7 +30,7 @@ type ( Command = ctrl.Cmd CommandID string CommandType = ctrl.Command - Timestamp = primitive.Timestamp + Timestamp = bson.Timestamp ) const ( @@ -124,7 +124,7 @@ type OpLock struct { // Node is `host:port` pair of an agent that acquired the lock. Node string `json:"node,omitempty"` // Heartbeat is the last cluster time seen by an agent that acquired the lock. - Heartbeat primitive.Timestamp `json:"hb"` + Heartbeat bson.Timestamp `json:"hb"` err error } @@ -214,7 +214,7 @@ func CanDeleteIncrementalBackup( func ListDeleteBackupBefore( ctx context.Context, client *Client, - ts primitive.Timestamp, + ts bson.Timestamp, bcpType BackupType, profile string, ) ([]BackupMetadata, error) { @@ -224,7 +224,7 @@ func ListDeleteBackupBefore( func ListDeleteChunksBefore( ctx context.Context, client *Client, - ts primitive.Timestamp, + ts bson.Timestamp, ) ([]OplogChunk, error) { r, err := backup.MakeCleanupInfo(ctx, client.conn, ts, "") return r.Chunks, err diff --git a/sdk/util.go b/sdk/util.go index e9c97eace..544d0de5b 100644 --- a/sdk/util.go +++ b/sdk/util.go @@ -3,10 +3,9 @@ package sdk import ( "context" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" "github.com/percona/percona-backup-mongodb/pbm/backup" "github.com/percona/percona-backup-mongodb/pbm/ctrl" @@ -35,10 +34,10 @@ func IsHeartbeatStale(clusterTime, other Timestamp) bool { func ClusterTime(ctx context.Context, client *Client) (Timestamp, error) { info, err := topo.GetNodeInfo(ctx, client.conn.MongoClient()) if err != nil { - return primitive.Timestamp{}, err + return bson.Timestamp{}, err } if info.ClusterTime == nil { - return primitive.Timestamp{}, ErrMissedClusterTime + return bson.Timestamp{}, ErrMissedClusterTime } return info.ClusterTime.ClusterTime, nil @@ -112,15 +111,15 @@ func FindCommandIDByName(ctx context.Context, c *Client, name string) (CommandID } type DiagnosticReport struct { - OPID string `json:"opid" bson:"opid"` - ClusterTime primitive.Timestamp `json:"cluster_time" bson:"cluster_time"` - ServerVersion string `json:"server_version" bson:"server_version"` - FCV string `json:"fcv" bson:"fcv"` - Command *Command `json:"command" bson:"command"` - Members []topo.Shard `json:"replsets" bson:"replsets"` - Agents []AgentStatus `json:"agents" bson:"agents"` - Locks []lock.LockData `json:"locks,omitempty" bson:"locks,omitempty"` - OpLocks []lock.LockData `json:"op_locks,omitempty" bson:"op_locks,omitempty"` + OPID string `json:"opid" bson:"opid"` + ClusterTime bson.Timestamp `json:"cluster_time" bson:"cluster_time"` + ServerVersion string `json:"server_version" bson:"server_version"` + FCV string `json:"fcv" bson:"fcv"` + Command *Command `json:"command" bson:"command"` + Members []topo.Shard `json:"replsets" bson:"replsets"` + Agents []AgentStatus `json:"agents" bson:"agents"` + Locks []lock.LockData `json:"locks,omitempty" bson:"locks,omitempty"` + OpLocks []lock.LockData `json:"op_locks,omitempty" bson:"op_locks,omitempty"` } func Diagnostic(ctx context.Context, c *Client, cid CommandID) (*DiagnosticReport, error) { diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go new file mode 100644 index 000000000..c602e77d1 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go @@ -0,0 +1,240 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package resource + +import ( + "fmt" + "strings" +) + +const ( + providersKey = "providers" + subscriptionsKey = "subscriptions" + resourceGroupsLowerKey = "resourcegroups" + locationsKey = "locations" + builtInResourceNamespace = "Microsoft.Resources" +) + +// RootResourceID defines the tenant as the root parent of all other ResourceID. +var RootResourceID = &ResourceID{ + Parent: nil, + ResourceType: TenantResourceType, + Name: "", +} + +// ResourceID represents a resource ID such as `/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg`. +// Don't create this type directly, use [ParseResourceID] instead. Fields are considered immutable and shouldn't be +// modified after creation. +type ResourceID struct { + // Parent is the parent ResourceID of this instance. + // Can be nil if there is no parent. + Parent *ResourceID + + // SubscriptionID is the subscription ID in this resource ID. + // The value can be empty if the resource ID does not contain a subscription ID. + SubscriptionID string + + // ResourceGroupName is the resource group name in this resource ID. + // The value can be empty if the resource ID does not contain a resource group name. + ResourceGroupName string + + // Provider represents the provider name in this resource ID. + // This is only valid when the resource ID represents a resource provider. + // Example: `/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Insights` + Provider string + + // Location is the location in this resource ID. + // The value can be empty if the resource ID does not contain a location name. + Location string + + // ResourceType represents the type of this resource ID. + ResourceType ResourceType + + // Name is the resource name of this resource ID. + Name string + + isChild bool + stringValue string +} + +// ParseResourceID parses a string to an instance of ResourceID +func ParseResourceID(id string) (*ResourceID, error) { + if len(id) == 0 { + return nil, fmt.Errorf("invalid resource ID: id cannot be empty") + } + + if !strings.HasPrefix(id, "/") { + return nil, fmt.Errorf("invalid resource ID: resource id '%s' must start with '/'", id) + } + + parts := splitStringAndOmitEmpty(id, "/") + + if len(parts) < 2 { + return nil, fmt.Errorf("invalid resource ID: %s", id) + } + + if !strings.EqualFold(parts[0], subscriptionsKey) && !strings.EqualFold(parts[0], providersKey) { + return nil, fmt.Errorf("invalid resource ID: %s", id) + } + + return appendNext(RootResourceID, parts, id) +} + +// String returns the string of the ResourceID +func (id *ResourceID) String() string { + return id.stringValue +} + +// MarshalText returns a textual representation of the ResourceID +func (id *ResourceID) MarshalText() ([]byte, error) { + return []byte(id.String()), nil +} + +// UnmarshalText decodes the textual representation of a ResourceID +func (id *ResourceID) UnmarshalText(text []byte) error { + newId, err := ParseResourceID(string(text)) + if err != nil { + return err + } + *id = *newId + return nil +} + +func newResourceID(parent *ResourceID, resourceTypeName string, resourceName string) *ResourceID { + id := &ResourceID{} + id.init(parent, chooseResourceType(resourceTypeName, parent), resourceName, true) + return id +} + +func newResourceIDWithResourceType(parent *ResourceID, resourceType ResourceType, resourceName string) *ResourceID { + id := &ResourceID{} + id.init(parent, resourceType, resourceName, true) + return id +} + +func newResourceIDWithProvider(parent *ResourceID, providerNamespace, resourceTypeName, resourceName string) *ResourceID { + id := &ResourceID{} + id.init(parent, NewResourceType(providerNamespace, resourceTypeName), resourceName, false) + return id +} + +func chooseResourceType(resourceTypeName string, parent *ResourceID) ResourceType { + if strings.EqualFold(resourceTypeName, resourceGroupsLowerKey) && isSubscriptionResource(parent) { + return ResourceGroupResourceType + } else if strings.EqualFold(resourceTypeName, subscriptionsKey) && isTenantResource(parent) { + return SubscriptionResourceType + } + + return parent.ResourceType.AppendChild(resourceTypeName) +} + +func (id *ResourceID) init(parent *ResourceID, resourceType ResourceType, name string, isChild bool) { + if parent != nil { + id.Provider = parent.Provider + id.SubscriptionID = parent.SubscriptionID + id.ResourceGroupName = parent.ResourceGroupName + id.Location = parent.Location + } + + if resourceType.String() == SubscriptionResourceType.String() { + id.SubscriptionID = name + } + + if resourceType.lastType() == locationsKey { + id.Location = name + } + + if resourceType.String() == ResourceGroupResourceType.String() { + id.ResourceGroupName = name + } + + if resourceType.String() == ProviderResourceType.String() { + id.Provider = name + } + + if parent == nil { + id.Parent = RootResourceID + } else { + id.Parent = parent + } + id.isChild = isChild + id.ResourceType = resourceType + id.Name = name + id.stringValue = id.Parent.String() + if id.isChild { + id.stringValue += "/" + id.ResourceType.lastType() + if id.Name != "" { + id.stringValue += "/" + id.Name + } + } else { + id.stringValue += fmt.Sprintf("/providers/%s/%s/%s", id.ResourceType.Namespace, id.ResourceType.Type, id.Name) + } +} + +func appendNext(parent *ResourceID, parts []string, id string) (*ResourceID, error) { + if len(parts) == 0 { + return parent, nil + } + + if len(parts) == 1 { + // subscriptions and resourceGroups are not valid ids without their names + if strings.EqualFold(parts[0], subscriptionsKey) && isTenantResource(parent) || strings.EqualFold(parts[0], resourceGroupsLowerKey) && isSubscriptionResource(parent) { + return nil, fmt.Errorf("invalid resource ID: %s", id) + } + + // resourceGroup must contain either child or provider resource type + if isResourceGroupResource(parent) { + return nil, fmt.Errorf("invalid resource ID: %s", id) + } + + return newResourceID(parent, parts[0], ""), nil + } + + if strings.EqualFold(parts[0], providersKey) && (len(parts) == 2 || strings.EqualFold(parts[2], providersKey)) { + // provider resource can only be on a tenant or a subscription parent + if !isSubscriptionResource(parent) && !isTenantResource(parent) { + return nil, fmt.Errorf("invalid resource ID: %s", id) + } + + return appendNext(newResourceIDWithResourceType(parent, ProviderResourceType, parts[1]), parts[2:], id) + } + + if len(parts) > 3 && strings.EqualFold(parts[0], providersKey) { + return appendNext(newResourceIDWithProvider(parent, parts[1], parts[2], parts[3]), parts[4:], id) + } + + if len(parts) > 1 && !strings.EqualFold(parts[0], providersKey) { + return appendNext(newResourceID(parent, parts[0], parts[1]), parts[2:], id) + } + + return nil, fmt.Errorf("invalid resource ID: %s", id) +} + +func splitStringAndOmitEmpty(v, sep string) []string { + r := make([]string, 0) + for _, s := range strings.Split(v, sep) { + s = strings.TrimSpace(s) + if len(s) == 0 { + continue + } + r = append(r, s) + } + + return r +} + +// isTenantResource returns true if the resourceID represents a tenant resource. The condition is resource ID matched with TenantResourceType and has no parent. +func isTenantResource(resourceID *ResourceID) bool { + return resourceID != nil && strings.EqualFold(resourceID.ResourceType.String(), TenantResourceType.String()) && resourceID.Parent == nil +} + +// isSubscriptionResource returns true if the resourceID represents a subscription resource. The condition is resource ID matched with SubscriptionResourceType and its parent is a tenant resource. +func isSubscriptionResource(resourceID *ResourceID) bool { + return resourceID != nil && strings.EqualFold(resourceID.ResourceType.String(), SubscriptionResourceType.String()) && isTenantResource(resourceID.Parent) +} + +// isResourceGroupResource returns true if the resourceID represents a resource group resource. The condition is resource ID matched with ResourceGroupResourceType and its parent is a subscription resource. +func isResourceGroupResource(resourceID *ResourceID) bool { + return resourceID != nil && strings.EqualFold(resourceID.ResourceType.String(), ResourceGroupResourceType.String()) && isSubscriptionResource(resourceID.Parent) +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_type.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_type.go new file mode 100644 index 000000000..34d09b6d7 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_type.go @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package resource + +import ( + "fmt" + "strings" +) + +// SubscriptionResourceType is the ResourceType of a subscription +var SubscriptionResourceType = NewResourceType(builtInResourceNamespace, "subscriptions") + +// ResourceGroupResourceType is the ResourceType of a resource group +var ResourceGroupResourceType = NewResourceType(builtInResourceNamespace, "resourceGroups") + +// TenantResourceType is the ResourceType of a tenant +var TenantResourceType = NewResourceType(builtInResourceNamespace, "tenants") + +// ProviderResourceType is the ResourceType of a provider +var ProviderResourceType = NewResourceType(builtInResourceNamespace, "providers") + +// ResourceType represents an Azure resource type, e.g. "Microsoft.Network/virtualNetworks/subnets". +// Don't create this type directly, use ParseResourceType or NewResourceType instead. +type ResourceType struct { + // Namespace is the namespace of the resource type. + // e.g. "Microsoft.Network" in resource type "Microsoft.Network/virtualNetworks/subnets" + Namespace string + + // Type is the full type name of the resource type. + // e.g. "virtualNetworks/subnets" in resource type "Microsoft.Network/virtualNetworks/subnets" + Type string + + // Types is the slice of all the sub-types of this resource type. + // e.g. ["virtualNetworks", "subnets"] in resource type "Microsoft.Network/virtualNetworks/subnets" + Types []string + + stringValue string +} + +// String returns the string of the ResourceType +func (t ResourceType) String() string { + return t.stringValue +} + +// IsParentOf returns true when the receiver is the parent resource type of the child. +func (t ResourceType) IsParentOf(child ResourceType) bool { + if !strings.EqualFold(t.Namespace, child.Namespace) { + return false + } + if len(t.Types) >= len(child.Types) { + return false + } + for i := range t.Types { + if !strings.EqualFold(t.Types[i], child.Types[i]) { + return false + } + } + + return true +} + +// AppendChild creates an instance of ResourceType using the receiver as the parent with childType appended to it. +func (t ResourceType) AppendChild(childType string) ResourceType { + return NewResourceType(t.Namespace, fmt.Sprintf("%s/%s", t.Type, childType)) +} + +// NewResourceType creates an instance of ResourceType using a provider namespace +// such as "Microsoft.Network" and type such as "virtualNetworks/subnets". +func NewResourceType(providerNamespace, typeName string) ResourceType { + return ResourceType{ + Namespace: providerNamespace, + Type: typeName, + Types: splitStringAndOmitEmpty(typeName, "/"), + stringValue: fmt.Sprintf("%s/%s", providerNamespace, typeName), + } +} + +// ParseResourceType parses the ResourceType from a resource type string (e.g. Microsoft.Network/virtualNetworks/subsets) +// or a resource identifier string. +// e.g. /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRg/providers/Microsoft.Network/virtualNetworks/vnet/subnets/mySubnet) +func ParseResourceType(resourceIDOrType string) (ResourceType, error) { + // split the path into segments + parts := splitStringAndOmitEmpty(resourceIDOrType, "/") + + // There must be at least a namespace and type name + if len(parts) < 1 { + return ResourceType{}, fmt.Errorf("invalid resource ID or type: %s", resourceIDOrType) + } + + // if the type is just subscriptions, it is a built-in type in the Microsoft.Resources namespace + if len(parts) == 1 { + // Simple resource type + return NewResourceType(builtInResourceNamespace, parts[0]), nil + } else if strings.Contains(parts[0], ".") { + // Handle resource types (Microsoft.Compute/virtualMachines, Microsoft.Network/virtualNetworks/subnets) + // it is a full type name + return NewResourceType(parts[0], strings.Join(parts[1:], "/")), nil + } else { + // Check if ResourceID + id, err := ParseResourceID(resourceIDOrType) + if err != nil { + return ResourceType{}, err + } + return NewResourceType(id.ResourceType.Namespace, id.ResourceType.Type), nil + } +} + +func (t ResourceType) lastType() string { + return t.Types[len(t.Types)-1] +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/policy/policy.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/policy/policy.go new file mode 100644 index 000000000..787c8e503 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/policy/policy.go @@ -0,0 +1,105 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package policy + +import ( + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" +) + +// BearerTokenOptions configures the bearer token policy's behavior. +type BearerTokenOptions struct { + // AuxiliaryTenants are additional tenant IDs for authenticating cross-tenant requests. + // The policy will add a token from each of these tenants to every request. The + // authenticating user or service principal must be a guest in these tenants, and the + // policy's credential must support multitenant authentication. + AuxiliaryTenants []string + + // InsecureAllowCredentialWithHTTP enables authenticated requests over HTTP. + // By default, authenticated requests to an HTTP endpoint are rejected by the client. + // WARNING: setting this to true will allow sending the authentication key in clear text. Use with caution. + InsecureAllowCredentialWithHTTP bool + + // Scopes contains the list of permission scopes required for the token. + Scopes []string +} + +// RegistrationOptions configures the registration policy's behavior. +// All zero-value fields will be initialized with their default values. +type RegistrationOptions struct { + policy.ClientOptions + + // MaxAttempts is the total number of times to attempt automatic registration + // in the event that an attempt fails. + // The default value is 3. + // Set to a value less than zero to disable the policy. + MaxAttempts int + + // PollingDelay is the amount of time to sleep between polling intervals. + // The default value is 15 seconds. + // A value less than zero means no delay between polling intervals (not recommended). + PollingDelay time.Duration + + // PollingDuration is the amount of time to wait before abandoning polling. + // The default valule is 5 minutes. + // NOTE: Setting this to a small value might cause the policy to prematurely fail. + PollingDuration time.Duration + + // StatusCodes contains the slice of custom HTTP status codes to use instead + // of the default http.StatusConflict. This should only be set if a service + // returns a non-standard HTTP status code when unregistered. + StatusCodes []int +} + +// ClientOptions contains configuration settings for a client's pipeline. +type ClientOptions struct { + policy.ClientOptions + + // AuxiliaryTenants are additional tenant IDs for authenticating cross-tenant requests. + // The client will add a token from each of these tenants to every request. The + // authenticating user or service principal must be a guest in these tenants, and the + // client's credential must support multitenant authentication. + AuxiliaryTenants []string + + // DisableRPRegistration disables the auto-RP registration policy. Defaults to false. + DisableRPRegistration bool +} + +// Clone return a deep copy of the current options. +func (o *ClientOptions) Clone() *ClientOptions { + if o == nil { + return nil + } + copiedOptions := *o + copiedOptions.Cloud.Services = copyMap(copiedOptions.Cloud.Services) + copiedOptions.Logging.AllowedHeaders = copyArray(copiedOptions.Logging.AllowedHeaders) + copiedOptions.Logging.AllowedQueryParams = copyArray(copiedOptions.Logging.AllowedQueryParams) + copiedOptions.Retry.StatusCodes = copyArray(copiedOptions.Retry.StatusCodes) + copiedOptions.PerRetryPolicies = copyArray(copiedOptions.PerRetryPolicies) + copiedOptions.PerCallPolicies = copyArray(copiedOptions.PerCallPolicies) + return &copiedOptions +} + +// copyMap return a new map with all the key value pair in the src map +func copyMap[K comparable, V any](src map[K]V) map[K]V { + if src == nil { + return nil + } + copiedMap := make(map[K]V) + for k, v := range src { + copiedMap[k] = v + } + return copiedMap +} + +// copyMap return a new array with all the elements in the src array +func copyArray[T any](src []T) []T { + if src == nil { + return nil + } + copiedArray := make([]T, len(src)) + copy(copiedArray, src) + return copiedArray +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/pipeline.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/pipeline.go new file mode 100644 index 000000000..fa0f29206 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/pipeline.go @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package runtime + +import ( + "errors" + "reflect" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + armpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" + azpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" +) + +// NewPipeline creates a pipeline from connection options. Policies from ClientOptions are +// placed after policies from PipelineOptions. The telemetry policy, when enabled, will +// use the specified module and version info. +func NewPipeline(module, version string, cred azcore.TokenCredential, plOpts azruntime.PipelineOptions, options *armpolicy.ClientOptions) (azruntime.Pipeline, error) { + if options == nil { + options = &armpolicy.ClientOptions{} + } + conf, err := getConfiguration(&options.ClientOptions) + if err != nil { + return azruntime.Pipeline{}, err + } + authPolicy := NewBearerTokenPolicy(cred, &armpolicy.BearerTokenOptions{ + AuxiliaryTenants: options.AuxiliaryTenants, + InsecureAllowCredentialWithHTTP: options.InsecureAllowCredentialWithHTTP, + Scopes: []string{conf.Audience + "/.default"}, + }) + // we don't want to modify the underlying array in plOpts.PerRetry + perRetry := make([]azpolicy.Policy, len(plOpts.PerRetry), len(plOpts.PerRetry)+1) + copy(perRetry, plOpts.PerRetry) + perRetry = append(perRetry, authPolicy, exported.PolicyFunc(httpTraceNamespacePolicy)) + plOpts.PerRetry = perRetry + if !options.DisableRPRegistration { + regRPOpts := armpolicy.RegistrationOptions{ClientOptions: options.ClientOptions} + regPolicy, err := NewRPRegistrationPolicy(cred, ®RPOpts) + if err != nil { + return azruntime.Pipeline{}, err + } + // we don't want to modify the underlying array in plOpts.PerCall + perCall := make([]azpolicy.Policy, len(plOpts.PerCall), len(plOpts.PerCall)+1) + copy(perCall, plOpts.PerCall) + perCall = append(perCall, regPolicy) + plOpts.PerCall = perCall + } + if plOpts.APIVersion.Name == "" { + plOpts.APIVersion.Name = "api-version" + } + return azruntime.NewPipeline(module, version, plOpts, &options.ClientOptions), nil +} + +func getConfiguration(o *azpolicy.ClientOptions) (cloud.ServiceConfiguration, error) { + c := cloud.AzurePublic + if !reflect.ValueOf(o.Cloud).IsZero() { + c = o.Cloud + } + if conf, ok := c.Services[cloud.ResourceManager]; ok && conf.Endpoint != "" && conf.Audience != "" { + return conf, nil + } else { + return conf, errors.New("provided Cloud field is missing Azure Resource Manager configuration") + } +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_bearer_token.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_bearer_token.go new file mode 100644 index 000000000..8ad3d5400 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_bearer_token.go @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package runtime + +import ( + "context" + "fmt" + "net/http" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + armpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" + azpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/internal/temporal" +) + +const headerAuxiliaryAuthorization = "x-ms-authorization-auxiliary" + +// acquiringResourceState holds data for an auxiliary token request +type acquiringResourceState struct { + ctx context.Context + p *BearerTokenPolicy + tenant string +} + +// acquireAuxToken acquires a token from an auxiliary tenant. Only one thread/goroutine at a time ever calls this function. +func acquireAuxToken(state acquiringResourceState) (newResource azcore.AccessToken, newExpiration time.Time, err error) { + tk, err := state.p.cred.GetToken(state.ctx, azpolicy.TokenRequestOptions{ + EnableCAE: true, + Scopes: state.p.scopes, + TenantID: state.tenant, + }) + if err != nil { + return azcore.AccessToken{}, time.Time{}, err + } + return tk, tk.ExpiresOn, nil +} + +// BearerTokenPolicy authorizes requests with bearer tokens acquired from a TokenCredential. +type BearerTokenPolicy struct { + auxResources map[string]*temporal.Resource[azcore.AccessToken, acquiringResourceState] + btp *azruntime.BearerTokenPolicy + cred azcore.TokenCredential + scopes []string +} + +// NewBearerTokenPolicy creates a policy object that authorizes requests with bearer tokens. +// cred: an azcore.TokenCredential implementation such as a credential object from azidentity +// opts: optional settings. Pass nil to accept default values; this is the same as passing a zero-value options. +func NewBearerTokenPolicy(cred azcore.TokenCredential, opts *armpolicy.BearerTokenOptions) *BearerTokenPolicy { + if opts == nil { + opts = &armpolicy.BearerTokenOptions{} + } + p := &BearerTokenPolicy{cred: cred} + p.auxResources = make(map[string]*temporal.Resource[azcore.AccessToken, acquiringResourceState], len(opts.AuxiliaryTenants)) + for _, t := range opts.AuxiliaryTenants { + p.auxResources[t] = temporal.NewResource(acquireAuxToken) + } + p.scopes = make([]string, len(opts.Scopes)) + copy(p.scopes, opts.Scopes) + p.btp = azruntime.NewBearerTokenPolicy(cred, opts.Scopes, &azpolicy.BearerTokenOptions{ + InsecureAllowCredentialWithHTTP: opts.InsecureAllowCredentialWithHTTP, + AuthorizationHandler: azpolicy.AuthorizationHandler{ + OnRequest: p.onRequest, + }, + }) + return p +} + +// onRequest authorizes requests with one or more bearer tokens +func (b *BearerTokenPolicy) onRequest(req *azpolicy.Request, authNZ func(azpolicy.TokenRequestOptions) error) error { + // authorize the request with a token for the primary tenant + err := authNZ(azpolicy.TokenRequestOptions{Scopes: b.scopes}) + if err != nil || len(b.auxResources) == 0 { + return err + } + // add tokens for auxiliary tenants + as := acquiringResourceState{ + ctx: req.Raw().Context(), + p: b, + } + auxTokens := make([]string, 0, len(b.auxResources)) + for tenant, er := range b.auxResources { + as.tenant = tenant + auxTk, err := er.Get(as) + if err != nil { + return err + } + auxTokens = append(auxTokens, fmt.Sprintf("%s%s", shared.BearerTokenPrefix, auxTk.Token)) + } + req.Raw().Header.Set(headerAuxiliaryAuthorization, strings.Join(auxTokens, ", ")) + return nil +} + +// Do authorizes a request with a bearer token +func (b *BearerTokenPolicy) Do(req *azpolicy.Request) (*http.Response, error) { + return b.btp.Do(req) +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_register_rp.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_register_rp.go new file mode 100644 index 000000000..3bfb7d02d --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_register_rp.go @@ -0,0 +1,319 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package runtime + +import ( + "context" + "fmt" + "net/http" + "net/url" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource" + armpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" + azpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/internal/log" +) + +const ( + // LogRPRegistration entries contain information specific to the automatic registration of an RP. + // Entries of this classification are written IFF the policy needs to take any action. + LogRPRegistration log.Event = "RPRegistration" +) + +// init sets any default values +func setDefaults(r *armpolicy.RegistrationOptions) { + if r.MaxAttempts == 0 { + r.MaxAttempts = 3 + } else if r.MaxAttempts < 0 { + r.MaxAttempts = 0 + } + if r.PollingDelay == 0 { + r.PollingDelay = 15 * time.Second + } else if r.PollingDelay < 0 { + r.PollingDelay = 0 + } + if r.PollingDuration == 0 { + r.PollingDuration = 5 * time.Minute + } + if len(r.StatusCodes) == 0 { + r.StatusCodes = []int{http.StatusConflict} + } +} + +// NewRPRegistrationPolicy creates a policy object configured using the specified options. +// The policy controls whether an unregistered resource provider should automatically be +// registered. See https://aka.ms/rps-not-found for more information. +func NewRPRegistrationPolicy(cred azcore.TokenCredential, o *armpolicy.RegistrationOptions) (azpolicy.Policy, error) { + if o == nil { + o = &armpolicy.RegistrationOptions{} + } + conf, err := getConfiguration(&o.ClientOptions) + if err != nil { + return nil, err + } + authPolicy := NewBearerTokenPolicy(cred, &armpolicy.BearerTokenOptions{Scopes: []string{conf.Audience + "/.default"}}) + p := &rpRegistrationPolicy{ + endpoint: conf.Endpoint, + pipeline: runtime.NewPipeline(shared.Module, shared.Version, runtime.PipelineOptions{PerRetry: []azpolicy.Policy{authPolicy}}, &o.ClientOptions), + options: *o, + } + // init the copy + setDefaults(&p.options) + return p, nil +} + +type rpRegistrationPolicy struct { + endpoint string + pipeline runtime.Pipeline + options armpolicy.RegistrationOptions +} + +func (r *rpRegistrationPolicy) Do(req *azpolicy.Request) (*http.Response, error) { + if r.options.MaxAttempts == 0 { + // policy is disabled + return req.Next() + } + const registeredState = "Registered" + var rp string + var resp *http.Response + for attempts := 0; attempts < r.options.MaxAttempts; attempts++ { + var err error + // make the original request + resp, err = req.Next() + // getting a 409 is the first indication that the RP might need to be registered, check error response + if err != nil || !runtime.HasStatusCode(resp, r.options.StatusCodes...) { + return resp, err + } + var reqErr requestError + if err = runtime.UnmarshalAsJSON(resp, &reqErr); err != nil { + return resp, err + } + if reqErr.ServiceError == nil { + // missing service error info. just return the response + // to the caller so its error unmarshalling will kick in + return resp, err + } + if !isUnregisteredRPCode(reqErr.ServiceError.Code) { + // not a 409 due to unregistered RP. just return the response + // to the caller so its error unmarshalling will kick in + return resp, err + } + res, err := resource.ParseResourceID(req.Raw().URL.Path) + if err != nil { + return resp, err + } + rp = res.ResourceType.Namespace + logRegistrationExit := func(v any) { + log.Writef(LogRPRegistration, "END registration for %s: %v", rp, v) + } + log.Writef(LogRPRegistration, "BEGIN registration for %s", rp) + // create client and make the registration request + // we use the scheme and host from the original request + rpOps := &providersOperations{ + p: r.pipeline, + u: r.endpoint, + subID: res.SubscriptionID, + } + if _, err = rpOps.Register(&shared.ContextWithDeniedValues{Context: req.Raw().Context()}, rp); err != nil { + logRegistrationExit(err) + return resp, err + } + + // RP was registered, however we need to wait for the registration to complete + pollCtx, pollCancel := context.WithTimeout(&shared.ContextWithDeniedValues{Context: req.Raw().Context()}, r.options.PollingDuration) + var lastRegState string + for { + // get the current registration state + getResp, err := rpOps.Get(pollCtx, rp) + if err != nil { + pollCancel() + logRegistrationExit(err) + return resp, err + } + if getResp.Provider.RegistrationState != nil && !strings.EqualFold(*getResp.Provider.RegistrationState, lastRegState) { + // registration state has changed, or was updated for the first time + lastRegState = *getResp.Provider.RegistrationState + log.Writef(LogRPRegistration, "registration state is %s", lastRegState) + } + if strings.EqualFold(lastRegState, registeredState) { + // registration complete + pollCancel() + logRegistrationExit(lastRegState) + break + } + // wait before trying again + select { + case <-time.After(r.options.PollingDelay): + // continue polling + case <-pollCtx.Done(): + pollCancel() + logRegistrationExit(pollCtx.Err()) + return resp, pollCtx.Err() + } + } + // RP was successfully registered, retry the original request + err = req.RewindBody() + if err != nil { + return resp, err + } + } + // if we get here it means we exceeded the number of attempts + return resp, fmt.Errorf("exceeded attempts to register %s", rp) +} + +var unregisteredRPCodes = []string{ + "MissingSubscriptionRegistration", + "MissingRegistrationForResourceProvider", + "Subscription Not Registered", + "SubscriptionNotRegistered", +} + +func isUnregisteredRPCode(errorCode string) bool { + for _, code := range unregisteredRPCodes { + if strings.EqualFold(errorCode, code) { + return true + } + } + return false +} + +// minimal error definitions to simplify detection +type requestError struct { + ServiceError *serviceError `json:"error"` +} + +type serviceError struct { + Code string `json:"code"` +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +// the following code was copied from module armresources, providers.go and models.go +// only the minimum amount of code was copied to get this working and some edits were made. +/////////////////////////////////////////////////////////////////////////////////////////////// + +type providersOperations struct { + p runtime.Pipeline + u string + subID string +} + +// Get - Gets the specified resource provider. +func (client *providersOperations) Get(ctx context.Context, resourceProviderNamespace string) (providerResponse, error) { + req, err := client.getCreateRequest(ctx, resourceProviderNamespace) + if err != nil { + return providerResponse{}, err + } + resp, err := client.p.Do(req) + if err != nil { + return providerResponse{}, err + } + result, err := client.getHandleResponse(resp) + if err != nil { + return providerResponse{}, err + } + return result, nil +} + +// getCreateRequest creates the Get request. +func (client *providersOperations) getCreateRequest(ctx context.Context, resourceProviderNamespace string) (*azpolicy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}" + urlPath = strings.ReplaceAll(urlPath, "{resourceProviderNamespace}", url.PathEscape(resourceProviderNamespace)) + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subID)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.u, urlPath)) + if err != nil { + return nil, err + } + query := req.Raw().URL.Query() + query.Set("api-version", "2019-05-01") + req.Raw().URL.RawQuery = query.Encode() + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *providersOperations) getHandleResponse(resp *http.Response) (providerResponse, error) { + if !runtime.HasStatusCode(resp, http.StatusOK) { + return providerResponse{}, exported.NewResponseError(resp) + } + result := providerResponse{RawResponse: resp} + err := runtime.UnmarshalAsJSON(resp, &result.Provider) + if err != nil { + return providerResponse{}, err + } + return result, err +} + +// Register - Registers a subscription with a resource provider. +func (client *providersOperations) Register(ctx context.Context, resourceProviderNamespace string) (providerResponse, error) { + req, err := client.registerCreateRequest(ctx, resourceProviderNamespace) + if err != nil { + return providerResponse{}, err + } + resp, err := client.p.Do(req) + if err != nil { + return providerResponse{}, err + } + result, err := client.registerHandleResponse(resp) + if err != nil { + return providerResponse{}, err + } + return result, nil +} + +// registerCreateRequest creates the Register request. +func (client *providersOperations) registerCreateRequest(ctx context.Context, resourceProviderNamespace string) (*azpolicy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}/register" + urlPath = strings.ReplaceAll(urlPath, "{resourceProviderNamespace}", url.PathEscape(resourceProviderNamespace)) + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subID)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.u, urlPath)) + if err != nil { + return nil, err + } + query := req.Raw().URL.Query() + query.Set("api-version", "2019-05-01") + req.Raw().URL.RawQuery = query.Encode() + return req, nil +} + +// registerHandleResponse handles the Register response. +func (client *providersOperations) registerHandleResponse(resp *http.Response) (providerResponse, error) { + if !runtime.HasStatusCode(resp, http.StatusOK) { + return providerResponse{}, exported.NewResponseError(resp) + } + result := providerResponse{RawResponse: resp} + err := runtime.UnmarshalAsJSON(resp, &result.Provider) + if err != nil { + return providerResponse{}, err + } + return result, err +} + +// ProviderResponse is the response envelope for operations that return a Provider type. +type providerResponse struct { + // Resource provider information. + Provider *provider + + // RawResponse contains the underlying HTTP response. + RawResponse *http.Response +} + +// Provider - Resource provider information. +type provider struct { + // The provider ID. + ID *string `json:"id,omitempty"` + + // The namespace of the resource provider. + Namespace *string `json:"namespace,omitempty"` + + // The registration policy of the resource provider. + RegistrationPolicy *string `json:"registrationPolicy,omitempty"` + + // The registration state of the resource provider. + RegistrationState *string `json:"registrationState,omitempty"` +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_trace_namespace.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_trace_namespace.go new file mode 100644 index 000000000..cc84d542d --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_trace_namespace.go @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package runtime + +import ( + "net/http" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing" +) + +// httpTraceNamespacePolicy is a policy that adds the az.namespace attribute to the current Span +func httpTraceNamespacePolicy(req *policy.Request) (resp *http.Response, err error) { + rawTracer := req.Raw().Context().Value(shared.CtxWithTracingTracer{}) + if tracer, ok := rawTracer.(tracing.Tracer); ok && tracer.Enabled() { + rt, err := resource.ParseResourceType(req.Raw().URL.Path) + if err == nil { + // add the namespace attribute to the current span + span := tracer.SpanFromContext(req.Raw().Context()) + span.SetAttributes(tracing.Attribute{Key: shared.TracingNamespaceAttrName, Value: rt.Namespace}) + } + } + return req.Next() +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/runtime.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/runtime.go new file mode 100644 index 000000000..0b58f542e --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/runtime.go @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package runtime + +import "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" + +func init() { + cloud.AzureChina.Services[cloud.ResourceManager] = cloud.ServiceConfiguration{ + Audience: "https://management.core.chinacloudapi.cn/", + Endpoint: "https://management.chinacloudapi.cn", + } + cloud.AzureGovernment.Services[cloud.ResourceManager] = cloud.ServiceConfiguration{ + Audience: "https://management.core.usgovcloudapi.net/", + Endpoint: "https://management.usgovcloudapi.net", + } + cloud.AzurePublic.Services[cloud.ResourceManager] = cloud.ServiceConfiguration{ + Audience: "https://management.core.windows.net/", + Endpoint: "https://management.azure.com", + } +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/.gitignore b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/.gitignore new file mode 100644 index 000000000..8cdb91036 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/.gitignore @@ -0,0 +1,4 @@ +# live test artifacts +Dockerfile +k8s.yaml +sshkey* diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/BREAKING_CHANGES.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/BREAKING_CHANGES.md new file mode 100644 index 000000000..567e6975b --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/BREAKING_CHANGES.md @@ -0,0 +1,20 @@ +# Breaking Changes + +## v1.8.0 + +### New errors from `NewManagedIdentityCredential` in some environments + +`NewManagedIdentityCredential` now returns an error when `ManagedIdentityCredentialOptions.ID` is set in a hosting environment whose managed identity API doesn't support user-assigned identities. `ManagedIdentityCredential.GetToken()` formerly logged a warning in these cases. Returning an error instead prevents the credential authenticating an unexpected identity. The affected hosting environments are: + * Azure Arc + * Azure ML (when a resource or object ID is specified; client IDs are supported) + * Cloud Shell + * Service Fabric + +## v1.6.0 + +### Behavioral change to `DefaultAzureCredential` in IMDS managed identity scenarios + +As of `azidentity` v1.6.0, `DefaultAzureCredential` makes a minor behavioral change when it uses IMDS managed +identity. It sends its first request to IMDS without the "Metadata" header, to expedite validating whether the endpoint +is available. This precedes the credential's first token request and is guaranteed to fail with a 400 error. This error +response can appear in logs but doesn't indicate authentication failed. diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md new file mode 100644 index 000000000..4a6349e16 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md @@ -0,0 +1,724 @@ +# Release History + +## 1.13.1 (2025-11-10) + +### Bugs Fixed + +- `AzureCLICredential` quoted arguments incorrectly on Windows + +## 1.13.0 (2025-10-07) + +### Features Added + +- Added `AzurePowerShellCredential`, which authenticates as the identity logged in to Azure PowerShell + (thanks [ArmaanMcleod](https://github.com/ArmaanMcleod)) +- When `AZURE_TOKEN_CREDENTIALS` is set to `ManagedIdentityCredential`, `DefaultAzureCredential` behaves the same as + does `ManagedIdentityCredential` when used directly. It doesn't apply special retry configuration or attempt to + determine whether IMDS is available. ([#25265](https://github.com/Azure/azure-sdk-for-go/issues/25265)) + +### Breaking Changes + +* Removed the `WorkloadIdentityCredential` support for identity binding mode added in v1.13.0-beta.1. + It will return in v1.14.0-beta.1 + +## 1.13.0-beta.1 (2025-09-17) + +### Features Added + +- Added `AzurePowerShellCredential`, which authenticates as the identity logged in to Azure PowerShell + (thanks [ArmaanMcleod](https://github.com/ArmaanMcleod)) +- `WorkloadIdentityCredential` supports identity binding mode ([#25056](https://github.com/Azure/azure-sdk-for-go/issues/25056)) + +## 1.12.0 (2025-09-16) + +### Features Added +- Added `DefaultAzureCredentialOptions.RequireAzureTokenCredentials`. `NewDefaultAzureCredential` returns an + error when this option is true and the environment variable `AZURE_TOKEN_CREDENTIALS` has no value. + +### Other Changes +- `AzureDeveloperCLICredential` no longer hangs when AZD_DEBUG is set +- `GetToken` methods of `AzureCLICredential` and `AzureDeveloperCLICredential` return an error when + `TokenRequestOptions.Claims` has a value because these credentials can't acquire a token in that + case. The error messages describe the action required to get a token. + +## 1.11.0 (2025-08-05) + +### Other Changes +- `DefaultAzureCredential` tries its next credential when a dev tool credential such as + `AzureCLICredential` returns an error + +## 1.11.0-beta.1 (2025-07-15) + +### Features Added +- `DefaultAzureCredential` allows selecting one of its credential types by name via environment variable + `AZURE_TOKEN_CREDENTIALS`. It will use only the selected type at runtime. For example, set + `AZURE_TOKEN_CREDENTIALS=WorkloadIdentityCredential` to have `DefaultAzureCredential` use only + `WorkloadIdentityCredential`. + +### Other Changes +- By default, `ManagedIdentityCredential` retries IMDS requests for a maximum of ~70 seconds as recommended + in IMDS documentation. In previous versions, it would stop retrying after ~54 seconds by default. + +## 1.10.1 (2025-06-10) + +### Bugs Fixed +- `AzureCLICredential` and `AzureDeveloperCLICredential` could wait indefinitely for subprocess output + +## 1.10.0 (2025-05-14) + +### Features Added +- `DefaultAzureCredential` reads environment variable `AZURE_TOKEN_CREDENTIALS` to enable a subset of its credentials: + - `dev` selects `AzureCLICredential` and `AzureDeveloperCLICredential` + - `prod` selects `EnvironmentCredential`, `WorkloadIdentityCredential` and `ManagedIdentityCredential` + +## 1.9.0 (2025-04-08) + +### Features Added +* `GetToken()` sets `AccessToken.RefreshOn` when the token provider specifies a value + +### Other Changes +* `NewManagedIdentityCredential` logs the configured user-assigned identity, if any +* Deprecated `UsernamePasswordCredential` because it can't support multifactor + authentication (MFA), which Microsoft Entra ID requires for most tenants. See + https://aka.ms/azsdk/identity/mfa for migration guidance. +* Updated dependencies + +## 1.8.2 (2025-02-12) + +### Other Changes +* Upgraded dependencies + +## 1.8.1 (2025-01-15) + +### Bugs Fixed +* User credential types inconsistently log access token scopes +* `DefaultAzureCredential` skips managed identity in Azure Container Instances +* Credentials having optional tenant IDs such as `AzureCLICredential` and + `InteractiveBrowserCredential` require setting `AdditionallyAllowedTenants` + when used with some clients + +### Other Changes +* `ChainedTokenCredential` and `DefaultAzureCredential` continue to their next + credential after `ManagedIdentityCredential` receives an unexpected response + from IMDS, indicating the response is from something else such as a proxy + +## 1.8.0 (2024-10-08) + +### Other Changes +* `AzurePipelinesCredential` sets an additional OIDC request header so that it + receives a 401 instead of a 302 after presenting an invalid system access token +* Allow logging of debugging headers for `AzurePipelinesCredential` and include + them in error messages + +## 1.8.0-beta.3 (2024-09-17) + +### Features Added +* Added `ObjectID` type for `ManagedIdentityCredentialOptions.ID` + +### Other Changes +* Removed redundant content from error messages + +## 1.8.0-beta.2 (2024-08-06) + +### Breaking Changes +* `NewManagedIdentityCredential` now returns an error when a user-assigned identity + is specified on a platform whose managed identity API doesn't support that. + `ManagedIdentityCredential.GetToken()` formerly logged a warning in these cases. + Returning an error instead prevents the credential authenticating an unexpected + identity, causing a client to act with unexpected privileges. The affected + platforms are: + * Azure Arc + * Azure ML (when a resource ID is specified; client IDs are supported) + * Cloud Shell + * Service Fabric + +### Other Changes +* If `DefaultAzureCredential` receives a non-JSON response when probing IMDS before + attempting to authenticate a managed identity, it continues to the next credential + in the chain instead of immediately returning an error. + +## 1.8.0-beta.1 (2024-07-17) + +### Features Added +* Restored persistent token caching feature + +### Breaking Changes +> These changes affect only code written against a beta version such as v1.7.0-beta.1 +* Redesigned the persistent caching API. Encryption is now required in all cases + and persistent cache construction is separate from credential construction. + The `PersistentUserAuthentication` example in the package docs has been updated + to demonstrate the new API. + +## 1.7.0 (2024-06-20) + +### Features Added +* `AzurePipelinesCredential` authenticates an Azure Pipelines service connection with + workload identity federation + +### Breaking Changes +> These changes affect only code written against a beta version such as v1.7.0-beta.1 +* Removed the persistent token caching API. It will return in v1.8.0-beta.1 + +## 1.7.0-beta.1 (2024-06-10) + +### Features Added +* Restored `AzurePipelinesCredential` and persistent token caching API + +## Breaking Changes +> These changes affect only code written against a beta version such as v1.6.0-beta.4 +* Values which `NewAzurePipelinesCredential` read from environment variables in + prior versions are now parameters +* Renamed `AzurePipelinesServiceConnectionCredentialOptions` to `AzurePipelinesCredentialOptions` + +### Bugs Fixed +* Managed identity bug fixes + +## 1.6.0 (2024-06-10) + +### Features Added +* `NewOnBehalfOfCredentialWithClientAssertions` creates an on-behalf-of credential + that authenticates with client assertions such as federated credentials + +### Breaking Changes +> These changes affect only code written against a beta version such as v1.6.0-beta.4 +* Removed `AzurePipelinesCredential` and the persistent token caching API. + They will return in v1.7.0-beta.1 + +### Bugs Fixed +* Managed identity bug fixes + +## 1.6.0-beta.4 (2024-05-14) + +### Features Added +* `AzurePipelinesCredential` authenticates an Azure Pipeline service connection with + workload identity federation + +## 1.6.0-beta.3 (2024-04-09) + +### Breaking Changes +* `DefaultAzureCredential` now sends a probe request with no retries for IMDS managed identity + environments to avoid excessive retry delays when the IMDS endpoint is not available. This + should improve credential chain resolution for local development scenarios. + +### Bugs Fixed +* `ManagedIdentityCredential` now specifies resource IDs correctly for Azure Container Instances + +## 1.5.2 (2024-04-09) + +### Bugs Fixed +* `ManagedIdentityCredential` now specifies resource IDs correctly for Azure Container Instances + +### Other Changes +* Restored v1.4.0 error behavior for empty tenant IDs +* Upgraded dependencies + +## 1.6.0-beta.2 (2024-02-06) + +### Breaking Changes +> These changes affect only code written against a beta version such as v1.6.0-beta.1 +* Replaced `ErrAuthenticationRequired` with `AuthenticationRequiredError`, a struct + type that carries the `TokenRequestOptions` passed to the `GetToken` call which + returned the error. + +### Bugs Fixed +* Fixed more cases in which credential chains like `DefaultAzureCredential` + should try their next credential after attempting managed identity + authentication in a Docker Desktop container + +### Other Changes +* `AzureCLICredential` uses the CLI's `expires_on` value for token expiration + +## 1.6.0-beta.1 (2024-01-17) + +### Features Added +* Restored persistent token caching API first added in v1.5.0-beta.1 +* Added `AzureCLICredentialOptions.Subscription` + +## 1.5.1 (2024-01-17) + +### Bugs Fixed +* `InteractiveBrowserCredential` handles `AdditionallyAllowedTenants` correctly + +## 1.5.0 (2024-01-16) + +### Breaking Changes +> These changes affect only code written against a beta version such as v1.5.0-beta.1 +* Removed persistent token caching. It will return in v1.6.0-beta.1 + +### Bugs Fixed +* Credentials now preserve MSAL headers e.g. X-Client-Sku + +### Other Changes +* Upgraded dependencies + +## 1.5.0-beta.2 (2023-11-07) + +### Features Added +* `DefaultAzureCredential` and `ManagedIdentityCredential` support Azure ML managed identity +* Added spans for distributed tracing. + +## 1.5.0-beta.1 (2023-10-10) + +### Features Added +* Optional persistent token caching for most credentials. Set `TokenCachePersistenceOptions` + on a credential's options to enable and configure this. See the package documentation for + this version and [TOKEN_CACHING.md](https://aka.ms/azsdk/go/identity/caching) for more + details. +* `AzureDeveloperCLICredential` authenticates with the Azure Developer CLI (`azd`). This + credential is also part of the `DefaultAzureCredential` authentication flow. + +## 1.4.0 (2023-10-10) + +### Bugs Fixed +* `ManagedIdentityCredential` will now retry when IMDS responds 410 or 503 + +## 1.4.0-beta.5 (2023-09-12) + +### Features Added +* Service principal credentials can request CAE tokens + +### Breaking Changes +> These changes affect only code written against a beta version such as v1.4.0-beta.4 +* Whether `GetToken` requests a CAE token is now determined by `TokenRequestOptions.EnableCAE`. Azure + SDK clients which support CAE will set this option automatically. Credentials no longer request CAE + tokens by default or observe the environment variable "AZURE_IDENTITY_DISABLE_CP1". + +### Bugs Fixed +* Credential chains such as `DefaultAzureCredential` now try their next credential, if any, when + managed identity authentication fails in a Docker Desktop container + ([#21417](https://github.com/Azure/azure-sdk-for-go/issues/21417)) + +## 1.4.0-beta.4 (2023-08-16) + +### Other Changes +* Upgraded dependencies + +## 1.3.1 (2023-08-16) + +### Other Changes +* Upgraded dependencies + +## 1.4.0-beta.3 (2023-08-08) + +### Bugs Fixed +* One invocation of `AzureCLICredential.GetToken()` and `OnBehalfOfCredential.GetToken()` + can no longer make two authentication attempts + +## 1.4.0-beta.2 (2023-07-14) + +### Other Changes +* `DefaultAzureCredentialOptions.TenantID` applies to workload identity authentication +* Upgraded dependencies + +## 1.4.0-beta.1 (2023-06-06) + +### Other Changes +* Re-enabled CAE support as in v1.3.0-beta.3 + +## 1.3.0 (2023-05-09) + +### Breaking Changes +> These changes affect only code written against a beta version such as v1.3.0-beta.5 +* Renamed `NewOnBehalfOfCredentialFromCertificate` to `NewOnBehalfOfCredentialWithCertificate` +* Renamed `NewOnBehalfOfCredentialFromSecret` to `NewOnBehalfOfCredentialWithSecret` + +### Other Changes +* Upgraded to MSAL v1.0.0 + +## 1.3.0-beta.5 (2023-04-11) + +### Breaking Changes +> These changes affect only code written against a beta version such as v1.3.0-beta.4 +* Moved `NewWorkloadIdentityCredential()` parameters into `WorkloadIdentityCredentialOptions`. + The constructor now reads default configuration from environment variables set by the Azure + workload identity webhook by default. + ([#20478](https://github.com/Azure/azure-sdk-for-go/pull/20478)) +* Removed CAE support. It will return in v1.4.0-beta.1 + ([#20479](https://github.com/Azure/azure-sdk-for-go/pull/20479)) + +### Bugs Fixed +* Fixed an issue in `DefaultAzureCredential` that could cause the managed identity endpoint check to fail in rare circumstances. + +## 1.3.0-beta.4 (2023-03-08) + +### Features Added +* Added `WorkloadIdentityCredentialOptions.AdditionallyAllowedTenants` and `.DisableInstanceDiscovery` + +### Bugs Fixed +* Credentials now synchronize within `GetToken()` so a single instance can be shared among goroutines + ([#20044](https://github.com/Azure/azure-sdk-for-go/issues/20044)) + +### Other Changes +* Upgraded dependencies + +## 1.2.2 (2023-03-07) + +### Other Changes +* Upgraded dependencies + +## 1.3.0-beta.3 (2023-02-07) + +### Features Added +* By default, credentials set client capability "CP1" to enable support for + [Continuous Access Evaluation (CAE)](https://learn.microsoft.com/entra/identity-platform/app-resilience-continuous-access-evaluation). + This indicates to Microsoft Entra ID that your application can handle CAE claims challenges. + You can disable this behavior by setting the environment variable "AZURE_IDENTITY_DISABLE_CP1" to "true". +* `InteractiveBrowserCredentialOptions.LoginHint` enables pre-populating the login + prompt with a username ([#15599](https://github.com/Azure/azure-sdk-for-go/pull/15599)) +* Service principal and user credentials support ADFS authentication on Azure Stack. + Specify "adfs" as the credential's tenant. +* Applications running in private or disconnected clouds can prevent credentials from + requesting Microsoft Entra instance metadata by setting the `DisableInstanceDiscovery` + field on credential options. +* Many credentials can now be configured to authenticate in multiple tenants. The + options types for these credentials have an `AdditionallyAllowedTenants` field + that specifies additional tenants in which the credential may authenticate. + +## 1.3.0-beta.2 (2023-01-10) + +### Features Added +* Added `OnBehalfOfCredential` to support the on-behalf-of flow + ([#16642](https://github.com/Azure/azure-sdk-for-go/issues/16642)) + +### Bugs Fixed +* `AzureCLICredential` reports token expiration in local time (should be UTC) + +### Other Changes +* `AzureCLICredential` imposes its default timeout only when the `Context` + passed to `GetToken()` has no deadline +* Added `NewCredentialUnavailableError()`. This function constructs an error indicating + a credential can't authenticate and an encompassing `ChainedTokenCredential` should + try its next credential, if any. + +## 1.3.0-beta.1 (2022-12-13) + +### Features Added +* `WorkloadIdentityCredential` and `DefaultAzureCredential` support + Workload Identity Federation on Kubernetes. `DefaultAzureCredential` + support requires environment variable configuration as set by the + Workload Identity webhook. + ([#15615](https://github.com/Azure/azure-sdk-for-go/issues/15615)) + +## 1.2.0 (2022-11-08) + +### Other Changes +* This version includes all fixes and features from 1.2.0-beta.* + +## 1.2.0-beta.3 (2022-10-11) + +### Features Added +* `ManagedIdentityCredential` caches tokens in memory + +### Bugs Fixed +* `ClientCertificateCredential` sends only the leaf cert for SNI authentication + +## 1.2.0-beta.2 (2022-08-10) + +### Features Added +* Added `ClientAssertionCredential` to enable applications to authenticate + with custom client assertions + +### Other Changes +* Updated AuthenticationFailedError with links to TROUBLESHOOTING.md for relevant errors +* Upgraded `microsoft-authentication-library-for-go` requirement to v0.6.0 + +## 1.2.0-beta.1 (2022-06-07) + +### Features Added +* `EnvironmentCredential` reads certificate passwords from `AZURE_CLIENT_CERTIFICATE_PASSWORD` + ([#17099](https://github.com/Azure/azure-sdk-for-go/pull/17099)) + +## 1.1.0 (2022-06-07) + +### Features Added +* `ClientCertificateCredential` and `ClientSecretCredential` support ESTS-R. First-party + applications can set environment variable `AZURE_REGIONAL_AUTHORITY_NAME` with a + region name. + ([#15605](https://github.com/Azure/azure-sdk-for-go/issues/15605)) + +## 1.0.1 (2022-06-07) + +### Other Changes +* Upgrade `microsoft-authentication-library-for-go` requirement to v0.5.1 + ([#18176](https://github.com/Azure/azure-sdk-for-go/issues/18176)) + +## 1.0.0 (2022-05-12) + +### Features Added +* `DefaultAzureCredential` reads environment variable `AZURE_CLIENT_ID` for the + client ID of a user-assigned managed identity + ([#17293](https://github.com/Azure/azure-sdk-for-go/pull/17293)) + +### Breaking Changes +* Removed `AuthorizationCodeCredential`. Use `InteractiveBrowserCredential` instead + to authenticate a user with the authorization code flow. +* Instances of `AuthenticationFailedError` are now returned by pointer. +* `GetToken()` returns `azcore.AccessToken` by value + +### Bugs Fixed +* `AzureCLICredential` panics after receiving an unexpected error type + ([#17490](https://github.com/Azure/azure-sdk-for-go/issues/17490)) + +### Other Changes +* `GetToken()` returns an error when the caller specifies no scope +* Updated to the latest versions of `golang.org/x/crypto`, `azcore` and `internal` + +## 0.14.0 (2022-04-05) + +### Breaking Changes +* This module now requires Go 1.18 +* Removed `AuthorityHost`. Credentials are now configured for sovereign or private + clouds with the API in `azcore/cloud`, for example: + ```go + // before + opts := azidentity.ClientSecretCredentialOptions{AuthorityHost: azidentity.AzureGovernment} + cred, err := azidentity.NewClientSecretCredential(tenantID, clientID, secret, &opts) + + // after + import "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" + + opts := azidentity.ClientSecretCredentialOptions{} + opts.Cloud = cloud.AzureGovernment + cred, err := azidentity.NewClientSecretCredential(tenantID, clientID, secret, &opts) + ``` + +## 0.13.2 (2022-03-08) + +### Bugs Fixed +* Prevented a data race in `DefaultAzureCredential` and `ChainedTokenCredential` + ([#17144](https://github.com/Azure/azure-sdk-for-go/issues/17144)) + +### Other Changes +* Upgraded App Service managed identity version from 2017-09-01 to 2019-08-01 + ([#17086](https://github.com/Azure/azure-sdk-for-go/pull/17086)) + +## 0.13.1 (2022-02-08) + +### Features Added +* `EnvironmentCredential` supports certificate SNI authentication when + `AZURE_CLIENT_SEND_CERTIFICATE_CHAIN` is "true". + ([#16851](https://github.com/Azure/azure-sdk-for-go/pull/16851)) + +### Bugs Fixed +* `ManagedIdentityCredential.GetToken()` now returns an error when configured for + a user assigned identity in Azure Cloud Shell (which doesn't support such identities) + ([#16946](https://github.com/Azure/azure-sdk-for-go/pull/16946)) + +### Other Changes +* `NewDefaultAzureCredential()` logs non-fatal errors. These errors are also included in the + error returned by `DefaultAzureCredential.GetToken()` when it's unable to acquire a token + from any source. ([#15923](https://github.com/Azure/azure-sdk-for-go/issues/15923)) + +## 0.13.0 (2022-01-11) + +### Breaking Changes +* Replaced `AuthenticationFailedError.RawResponse()` with a field having the same name +* Unexported `CredentialUnavailableError` +* Instances of `ChainedTokenCredential` will now skip looping through the list of source credentials and re-use the first successful credential on subsequent calls to `GetToken`. + * If `ChainedTokenCredentialOptions.RetrySources` is true, `ChainedTokenCredential` will continue to try all of the originally provided credentials each time the `GetToken` method is called. + * `ChainedTokenCredential.successfulCredential` will contain a reference to the last successful credential. + * `DefaultAzureCredenial` will also re-use the first successful credential on subsequent calls to `GetToken`. + * `DefaultAzureCredential.chain.successfulCredential` will also contain a reference to the last successful credential. + +### Other Changes +* `ManagedIdentityCredential` no longer probes IMDS before requesting a token + from it. Also, an error response from IMDS no longer disables a credential + instance. Following an error, a credential instance will continue to send + requests to IMDS as necessary. +* Adopted MSAL for user and service principal authentication +* Updated `azcore` requirement to 0.21.0 + +## 0.12.0 (2021-11-02) +### Breaking Changes +* Raised minimum go version to 1.16 +* Removed `NewAuthenticationPolicy()` from credentials. Clients should instead use azcore's + `runtime.NewBearerTokenPolicy()` to construct a bearer token authorization policy. +* The `AuthorityHost` field in credential options structs is now a custom type, + `AuthorityHost`, with underlying type `string` +* `NewChainedTokenCredential` has a new signature to accommodate a placeholder + options struct: + ```go + // before + cred, err := NewChainedTokenCredential(credA, credB) + + // after + cred, err := NewChainedTokenCredential([]azcore.TokenCredential{credA, credB}, nil) + ``` +* Removed `ExcludeAzureCLICredential`, `ExcludeEnvironmentCredential`, and `ExcludeMSICredential` + from `DefaultAzureCredentialOptions` +* `NewClientCertificateCredential` requires a `[]*x509.Certificate` and `crypto.PrivateKey` instead of + a path to a certificate file. Added `ParseCertificates` to simplify getting these in common cases: + ```go + // before + cred, err := NewClientCertificateCredential("tenant", "client-id", "/cert.pem", nil) + + // after + certData, err := os.ReadFile("/cert.pem") + certs, key, err := ParseCertificates(certData, password) + cred, err := NewClientCertificateCredential(tenantID, clientID, certs, key, nil) + ``` +* Removed `InteractiveBrowserCredentialOptions.ClientSecret` and `.Port` +* Removed `AADAuthenticationFailedError` +* Removed `id` parameter of `NewManagedIdentityCredential()`. User assigned identities are now + specified by `ManagedIdentityCredentialOptions.ID`: + ```go + // before + cred, err := NewManagedIdentityCredential("client-id", nil) + // or, for a resource ID + opts := &ManagedIdentityCredentialOptions{ID: ResourceID} + cred, err := NewManagedIdentityCredential("/subscriptions/...", opts) + + // after + clientID := ClientID("7cf7db0d-...") + opts := &ManagedIdentityCredentialOptions{ID: clientID} + // or, for a resource ID + resID: ResourceID("/subscriptions/...") + opts := &ManagedIdentityCredentialOptions{ID: resID} + cred, err := NewManagedIdentityCredential(opts) + ``` +* `DeviceCodeCredentialOptions.UserPrompt` has a new type: `func(context.Context, DeviceCodeMessage) error` +* Credential options structs now embed `azcore.ClientOptions`. In addition to changing literal initialization + syntax, this change renames `HTTPClient` fields to `Transport`. +* Renamed `LogCredential` to `EventCredential` +* `AzureCLICredential` no longer reads the environment variable `AZURE_CLI_PATH` +* `NewManagedIdentityCredential` no longer reads environment variables `AZURE_CLIENT_ID` and + `AZURE_RESOURCE_ID`. Use `ManagedIdentityCredentialOptions.ID` instead. +* Unexported `AuthenticationFailedError` and `CredentialUnavailableError` structs. In their place are two + interfaces having the same names. + +### Bugs Fixed +* `AzureCLICredential.GetToken` no longer mutates its `opts.Scopes` + +### Features Added +* Added connection configuration options to `DefaultAzureCredentialOptions` +* `AuthenticationFailedError.RawResponse()` returns the HTTP response motivating the error, + if available + +### Other Changes +* `NewDefaultAzureCredential()` returns `*DefaultAzureCredential` instead of `*ChainedTokenCredential` +* Added `TenantID` field to `DefaultAzureCredentialOptions` and `AzureCLICredentialOptions` + +## 0.11.0 (2021-09-08) +### Breaking Changes +* Unexported `AzureCLICredentialOptions.TokenProvider` and its type, + `AzureCLITokenProvider` + +### Bug Fixes +* `ManagedIdentityCredential.GetToken` returns `CredentialUnavailableError` + when IMDS has no assigned identity, signaling `DefaultAzureCredential` to + try other credentials + + +## 0.10.0 (2021-08-30) +### Breaking Changes +* Update based on `azcore` refactor [#15383](https://github.com/Azure/azure-sdk-for-go/pull/15383) + +## 0.9.3 (2021-08-20) + +### Bugs Fixed +* `ManagedIdentityCredential.GetToken` no longer mutates its `opts.Scopes` + +### Other Changes +* Bumps version of `azcore` to `v0.18.1` + + +## 0.9.2 (2021-07-23) +### Features Added +* Adding support for Service Fabric environment in `ManagedIdentityCredential` +* Adding an option for using a resource ID instead of client ID in `ManagedIdentityCredential` + + +## 0.9.1 (2021-05-24) +### Features Added +* Add LICENSE.txt and bump version information + + +## 0.9.0 (2021-05-21) +### Features Added +* Add support for authenticating in Azure Stack environments +* Enable user assigned identities for the IMDS scenario in `ManagedIdentityCredential` +* Add scope to resource conversion in `GetToken()` on `ManagedIdentityCredential` + + +## 0.8.0 (2021-01-20) +### Features Added +* Updating documentation + + +## 0.7.1 (2021-01-04) +### Features Added +* Adding port option to `InteractiveBrowserCredential` + + +## 0.7.0 (2020-12-11) +### Features Added +* Add `redirectURI` parameter back to authentication code flow + + +## 0.6.1 (2020-12-09) +### Features Added +* Updating query parameter in `ManagedIdentityCredential` and updating datetime string for parsing managed identity access tokens. + + +## 0.6.0 (2020-11-16) +### Features Added +* Remove `RedirectURL` parameter from auth code flow to align with the MSAL implementation which relies on the native client redirect URL. + + +## 0.5.0 (2020-10-30) +### Features Added +* Flattening credential options + + +## 0.4.3 (2020-10-21) +### Features Added +* Adding Azure Arc support in `ManagedIdentityCredential` + + +## 0.4.2 (2020-10-16) +### Features Added +* Typo fixes + + +## 0.4.1 (2020-10-16) +### Features Added +* Ensure authority hosts are only HTTPs + + +## 0.4.0 (2020-10-16) +### Features Added +* Adding options structs for credentials + + +## 0.3.0 (2020-10-09) +### Features Added +* Update `DeviceCodeCredential` callback + + +## 0.2.2 (2020-10-09) +### Features Added +* Add `AuthorizationCodeCredential` + + +## 0.2.1 (2020-10-06) +### Features Added +* Add `InteractiveBrowserCredential` + + +## 0.2.0 (2020-09-11) +### Features Added +* Refactor `azidentity` on top of `azcore` refactor +* Updated policies to conform to `policy.Policy` interface changes. +* Updated non-retriable errors to conform to `azcore.NonRetriableError`. +* Fixed calls to `Request.SetBody()` to include content type. +* Switched endpoints to string types and removed extra parsing code. + + +## 0.1.1 (2020-09-02) +### Features Added +* Add `AzureCLICredential` to `DefaultAzureCredential` chain + + +## 0.1.0 (2020-07-23) +### Features Added +* Initial Release. Azure Identity library that provides Microsoft Entra token authentication support for the SDK. diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/LICENSE.txt b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/LICENSE.txt new file mode 100644 index 000000000..48ea6616b --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Microsoft Corporation. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/MIGRATION.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/MIGRATION.md new file mode 100644 index 000000000..29b60baec --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/MIGRATION.md @@ -0,0 +1,307 @@ +# Migrating from autorest/adal to azidentity + +`azidentity` provides Microsoft Entra ID ([formerly Azure Active Directory](https://learn.microsoft.com/entra/fundamentals/new-name)) authentication for the newest Azure SDK modules (`github.com/azure-sdk-for-go/sdk/...`). Older Azure SDK packages (`github.com/azure-sdk-for-go/services/...`) use types from `github.com/go-autorest/autorest/adal` instead. + +This guide shows common authentication code using `autorest/adal` and its equivalent using `azidentity`. + +## Table of contents + +- [Acquire a token](#acquire-a-token) +- [Client certificate authentication](#client-certificate-authentication) +- [Client secret authentication](#client-secret-authentication) +- [Configuration](#configuration) +- [Device code authentication](#device-code-authentication) +- [Managed identity](#managed-identity) +- [Use azidentity credentials with older packages](#use-azidentity-credentials-with-older-packages) + +## Configuration + +### `autorest/adal` + +Token providers require a token audience (resource identifier) and an instance of `adal.OAuthConfig`, which requires a Microsoft Entra endpoint and tenant: + +```go +import "github.com/Azure/go-autorest/autorest/adal" + +oauthCfg, err := adal.NewOAuthConfig("https://login.chinacloudapi.cn", tenantID) +handle(err) + +spt, err := adal.NewServicePrincipalTokenWithSecret( + *oauthCfg, clientID, "https://management.chinacloudapi.cn/", &adal.ServicePrincipalTokenSecret{ClientSecret: secret}, +) +``` + +### `azidentity` + +A credential instance can acquire tokens for any audience. The audience for each token is determined by the client requesting it. Credentials require endpoint configuration only for sovereign or private clouds. The `azcore/cloud` package has predefined configuration for sovereign clouds such as Azure China: + +```go +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" +) + +clientOpts := azcore.ClientOptions{Cloud: cloud.AzureChina} + +cred, err := azidentity.NewClientSecretCredential( + tenantID, clientID, secret, &azidentity.ClientSecretCredentialOptions{ClientOptions: clientOpts}, +) +handle(err) +``` + +## Client secret authentication + +### `autorest/adal` + +```go +import ( + "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-06-01/subscriptions" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/adal" +) + +oauthCfg, err := adal.NewOAuthConfig("https://login.microsoftonline.com", tenantID) +handle(err) +spt, err := adal.NewServicePrincipalTokenWithSecret( + *oauthCfg, clientID, "https://management.azure.com/", &adal.ServicePrincipalTokenSecret{ClientSecret: secret}, +) +handle(err) + +client := subscriptions.NewClient() +client.Authorizer = autorest.NewBearerAuthorizer(spt) +``` + +### `azidentity` + +```go +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions" +) + +cred, err := azidentity.NewClientSecretCredential(tenantID, clientID, secret, nil) +handle(err) + +client, err := armsubscriptions.NewClient(cred, nil) +handle(err) +``` + +## Client certificate authentication + +### `autorest/adal` + +```go +import ( + "os" + + "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-06-01/subscriptions" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/adal" +) +certData, err := os.ReadFile("./example.pfx") +handle(err) + +certificate, rsaPrivateKey, err := decodePkcs12(certData, "") +handle(err) + +oauthCfg, err := adal.NewOAuthConfig("https://login.microsoftonline.com", tenantID) +handle(err) + +spt, err := adal.NewServicePrincipalTokenFromCertificate( + *oauthConfig, clientID, certificate, rsaPrivateKey, "https://management.azure.com/", +) + +client := subscriptions.NewClient() +client.Authorizer = autorest.NewBearerAuthorizer(spt) +``` + +### `azidentity` + +```go +import ( + "os" + + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions" +) + +certData, err := os.ReadFile("./example.pfx") +handle(err) + +certs, key, err := azidentity.ParseCertificates(certData, nil) +handle(err) + +cred, err = azidentity.NewClientCertificateCredential(tenantID, clientID, certs, key, nil) +handle(err) + +client, err := armsubscriptions.NewClient(cred, nil) +handle(err) +``` + +## Managed identity + +### `autorest/adal` + +```go +import ( + "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-06-01/subscriptions" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/adal" +) + +spt, err := adal.NewServicePrincipalTokenFromManagedIdentity("https://management.azure.com/", nil) +handle(err) + +client := subscriptions.NewClient() +client.Authorizer = autorest.NewBearerAuthorizer(spt) +``` + +### `azidentity` + +```go +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions" +) + +cred, err := azidentity.NewManagedIdentityCredential(nil) +handle(err) + +client, err := armsubscriptions.NewClient(cred, nil) +handle(err) +``` + +### User-assigned identities + +`autorest/adal`: + +```go +import "github.com/Azure/go-autorest/autorest/adal" + +opts := &adal.ManagedIdentityOptions{ClientID: "..."} +spt, err := adal.NewServicePrincipalTokenFromManagedIdentity("https://management.azure.com/") +handle(err) +``` + +`azidentity`: + +```go +import "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + +opts := azidentity.ManagedIdentityCredentialOptions{ID: azidentity.ClientID("...")} +cred, err := azidentity.NewManagedIdentityCredential(&opts) +handle(err) +``` + +## Device code authentication + +### `autorest/adal` + +```go +import ( + "fmt" + "net/http" + + "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-06-01/subscriptions" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/adal" +) + +oauthClient := &http.Client{} +oauthCfg, err := adal.NewOAuthConfig("https://login.microsoftonline.com", tenantID) +handle(err) +resource := "https://management.azure.com/" +deviceCode, err := adal.InitiateDeviceAuth(oauthClient, *oauthCfg, clientID, resource) +handle(err) + +// display instructions, wait for the user to authenticate +fmt.Println(*deviceCode.Message) +token, err := adal.WaitForUserCompletion(oauthClient, deviceCode) +handle(err) + +spt, err := adal.NewServicePrincipalTokenFromManualToken(*oauthCfg, clientID, resource, *token) +handle(err) + +client := subscriptions.NewClient() +client.Authorizer = autorest.NewBearerAuthorizer(spt) +``` + +### `azidentity` + +```go +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions" +) + +cred, err := azidentity.NewDeviceCodeCredential(nil) +handle(err) + +client, err := armsubscriptions.NewSubscriptionsClient(cred, nil) +handle(err) +``` + +`azidentity.DeviceCodeCredential` will guide a user through authentication, printing instructions to the console by default. The user prompt is customizable. For more information, see the [package documentation](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DeviceCodeCredential). + +## Acquire a token + +### `autorest/adal` + +```go +import "github.com/Azure/go-autorest/autorest/adal" + +oauthCfg, err := adal.NewOAuthConfig("https://login.microsoftonline.com", tenantID) +handle(err) + +spt, err := adal.NewServicePrincipalTokenWithSecret( + *oauthCfg, clientID, "https://vault.azure.net", &adal.ServicePrincipalTokenSecret{ClientSecret: secret}, +) + +err = spt.Refresh() +if err == nil { + token := spt.Token +} +``` + +### `azidentity` + +In ordinary usage, application code doesn't need to request tokens from credentials directly. Azure SDK clients handle token acquisition and refreshing internally. However, applications may call `GetToken()` to do so. All credential types have this method. + +```go +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" +) + +cred, err := azidentity.NewClientSecretCredential(tenantID, clientID, secret, nil) +handle(err) + +tk, err := cred.GetToken( + context.TODO(), policy.TokenRequestOptions{Scopes: []string{"https://vault.azure.net/.default"}}, +) +if err == nil { + token := tk.Token +} +``` + +Note that `azidentity` credentials use the Microsoft Entra endpoint, which requires OAuth 2 scopes instead of the resource identifiers `autorest/adal` expects. For more information, see [Microsoft Entra ID documentation](https://learn.microsoft.com/entra/identity-platform/permissions-consent-overview). + +## Use azidentity credentials with older packages + +The [azidext module](https://pkg.go.dev/github.com/jongio/azidext/go/azidext) provides an adapter for `azidentity` credential types. The adapter enables using the credential types with older Azure SDK clients. For example: + +```go +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-06-01/subscriptions" + "github.com/jongio/azidext/go/azidext" +) + +cred, err := azidentity.NewClientSecretCredential(tenantID, clientID, secret, nil) +handle(err) + +client := subscriptions.NewClient() +client.Authorizer = azidext.NewTokenCredentialAdapter(cred, []string{"https://management.azure.com//.default"}) +``` + + diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md new file mode 100644 index 000000000..127c25b72 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md @@ -0,0 +1,248 @@ +# Azure Identity Client Module for Go + +The Azure Identity module provides [Microsoft Entra ID](https://learn.microsoft.com/entra/fundamentals/whatis) token-based authentication support across the Azure SDK. It includes a set of `TokenCredential` implementations, which can be used with Azure SDK clients supporting token authentication. + +[![PkgGoDev](https://pkg.go.dev/badge/github.com/Azure/azure-sdk-for-go/sdk/azidentity)](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity) +| [Microsoft Entra ID documentation](https://learn.microsoft.com/entra/identity/) +| [Source code](https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/azidentity) + +# Getting started + +## Install the module + +This project uses [Go modules](https://github.com/golang/go/wiki/Modules) for versioning and dependency management. + +Install the Azure Identity module: + +```sh +go get -u github.com/Azure/azure-sdk-for-go/sdk/azidentity +``` + +## Prerequisites + +- an [Azure subscription](https://azure.microsoft.com/free/) +- [Supported](https://aka.ms/azsdk/go/supported-versions) version of Go + +### Authenticating during local development + +When debugging and executing code locally, developers typically use their own accounts to authenticate calls to Azure services. The `azidentity` module supports authenticating through developer tools to simplify local development. + +#### Authenticating via the Azure CLI + +`DefaultAzureCredential` and `AzureCLICredential` can authenticate as the user +signed in to the [Azure CLI](https://learn.microsoft.com/cli/azure). To sign in to the Azure CLI, run `az login`. On a system with a default web browser, the Azure CLI will launch the browser to authenticate a user. + +When no default browser is available, `az login` will use the device code +authentication flow. This can also be selected manually by running `az login --use-device-code`. + +#### Authenticate via the Azure Developer CLI + +Developers coding outside of an IDE can also use the [Azure Developer CLI](https://aka.ms/azure-dev) to authenticate. Applications using the `DefaultAzureCredential` or the `AzureDeveloperCLICredential` can use the account logged in to the Azure Developer CLI to authenticate calls in their application when running locally. + +To authenticate with the Azure Developer CLI, run `azd auth login`. On a system with a default web browser, `azd` will launch the browser to authenticate. On systems without a default web browser, run `azd auth login --use-device-code` to use the device code authentication flow. + +## Key concepts + +### Credentials + +A credential is a type which contains or can obtain the data needed for a +service client to authenticate requests. Service clients across the Azure SDK +accept a credential instance when they are constructed, and use that credential +to authenticate requests. + +The `azidentity` module focuses on OAuth authentication with Microsoft Entra ID. It offers a variety of credential types capable of acquiring a Microsoft Entra access token. See [Credential Types](#credential-types "Credential Types") for a list of this module's credential types. + +### DefaultAzureCredential + +`DefaultAzureCredential` simplifies authentication while developing apps that deploy to Azure by combining credentials used in Azure hosting environments with credentials used in local development. For more information, see [DefaultAzureCredential overview][dac_overview]. + +## Managed Identity + +`DefaultAzureCredential` and `ManagedIdentityCredential` support +[managed identity authentication](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/overview) +in any hosting environment which supports managed identities, such as (this list is not exhaustive): +* [Azure App Service](https://learn.microsoft.com/azure/app-service/overview-managed-identity) +* [Azure Arc](https://learn.microsoft.com/azure/azure-arc/servers/managed-identity-authentication) +* [Azure Cloud Shell](https://learn.microsoft.com/azure/cloud-shell/msi-authorization) +* [Azure Kubernetes Service](https://learn.microsoft.com/azure/aks/use-managed-identity) +* [Azure Service Fabric](https://learn.microsoft.com/azure/service-fabric/concepts-managed-identity) +* [Azure Virtual Machines](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/how-to-use-vm-token) + +## Examples + +- [Authenticate with DefaultAzureCredential](#authenticate-with-defaultazurecredential "Authenticate with DefaultAzureCredential") +- [Define a custom authentication flow with ChainedTokenCredential](#define-a-custom-authentication-flow-with-chainedtokencredential "Define a custom authentication flow with ChainedTokenCredential") +- [Specify a user-assigned managed identity for DefaultAzureCredential](#specify-a-user-assigned-managed-identity-for-defaultazurecredential) + +### Authenticate with DefaultAzureCredential + +This example demonstrates authenticating a client from the `armresources` module with `DefaultAzureCredential`. + +```go +cred, err := azidentity.NewDefaultAzureCredential(nil) +if err != nil { + // handle error +} + +client := armresources.NewResourceGroupsClient("subscription ID", cred, nil) +``` + +### Specify a user-assigned managed identity for DefaultAzureCredential + +To configure `DefaultAzureCredential` to authenticate a user-assigned managed identity, set the environment variable `AZURE_CLIENT_ID` to the identity's client ID. + +### Define a custom authentication flow with `ChainedTokenCredential` + +`DefaultAzureCredential` is generally the quickest way to get started developing apps for Azure. For more advanced scenarios, `ChainedTokenCredential` links multiple credential instances to be tried sequentially when authenticating. It will try each chained credential in turn until one provides a token or fails to authenticate due to an error. + +The following example demonstrates creating a credential, which will attempt to authenticate using managed identity. It will fall back to authenticating via the Azure CLI when a managed identity is unavailable. + +```go +managed, err := azidentity.NewManagedIdentityCredential(nil) +if err != nil { + // handle error +} +azCLI, err := azidentity.NewAzureCLICredential(nil) +if err != nil { + // handle error +} +chain, err := azidentity.NewChainedTokenCredential([]azcore.TokenCredential{managed, azCLI}, nil) +if err != nil { + // handle error +} + +client := armresources.NewResourceGroupsClient("subscription ID", chain, nil) +``` + +## Credential Types + +### Credential chains + +|Credential|Usage|Reference +|-|-|- +|[DefaultAzureCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DefaultAzureCredential)|Simplified authentication experience for getting started developing Azure apps|[DefaultAzureCredential overview][dac_overview]| +|[ChainedTokenCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ChainedTokenCredential)|Define custom authentication flows, composing multiple credentials|[ChainedTokenCredential overview][ctc_overview]| + +### Authenticating Azure-Hosted Applications + +|Credential|Usage +|-|- +|[EnvironmentCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#EnvironmentCredential)|Authenticate a service principal or user configured by environment variables +|[ManagedIdentityCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ManagedIdentityCredential)|Authenticate the managed identity of an Azure resource +|[WorkloadIdentityCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#WorkloadIdentityCredential)|Authenticate a workload identity on Kubernetes + +### Authenticating Service Principals + +|Credential|Usage +|-|- +|[AzurePipelinesCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzurePipelinesCredential)|Authenticate an Azure Pipelines [service connection](https://learn.microsoft.com/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml) +|[ClientAssertionCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientAssertionCredential)|Authenticate a service principal with a signed client assertion +|[ClientCertificateCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientCertificateCredential)|Authenticate a service principal with a certificate +|[ClientSecretCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientSecretCredential)|Authenticate a service principal with a secret + +### Authenticating Users + +|Credential|Usage +|-|- +|[InteractiveBrowserCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#InteractiveBrowserCredential)|Interactively authenticate a user with the default web browser +|[DeviceCodeCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DeviceCodeCredential)|Interactively authenticate a user on a device with limited UI + +### Authenticating via Development Tools + +|Credential|Usage +|-|- +|[AzureCLICredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzureCLICredential)|Authenticate as the user signed in to the Azure CLI +|[AzureDeveloperCLICredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzureDeveloperCLICredential)|Authenticates as the user signed in to the Azure Developer CLI +|[AzurePowerShellCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzurePowerShellCredential)|Authenticates as the user signed in to Azure PowerShell + +## Environment Variables + +`DefaultAzureCredential` and `EnvironmentCredential` can be configured with environment variables. Each type of authentication requires values for specific variables: + +### Service principal with secret + +|variable name|value +|-|- +|`AZURE_CLIENT_ID`|ID of a Microsoft Entra application +|`AZURE_TENANT_ID`|ID of the application's Microsoft Entra tenant +|`AZURE_CLIENT_SECRET`|one of the application's client secrets + +### Service principal with certificate + +|variable name|value +|-|- +|`AZURE_CLIENT_ID`|ID of a Microsoft Entra application +|`AZURE_TENANT_ID`|ID of the application's Microsoft Entra tenant +|`AZURE_CLIENT_CERTIFICATE_PATH`|path to a certificate file including private key +|`AZURE_CLIENT_CERTIFICATE_PASSWORD`|password of the certificate file, if any + +Configuration is attempted in the above order. For example, if values for a client secret and certificate are both present, the client secret will be used. + +## Token caching + +Token caching is an `azidentity` feature that allows apps to: + +* Cache tokens in memory (default) or on disk (opt-in). +* Improve resilience and performance. +* Reduce the number of requests made to Microsoft Entra ID to obtain access tokens. + +For more details, see the [token caching documentation](https://aka.ms/azsdk/go/identity/caching). + +## Troubleshooting + +### Error Handling + +Credentials return an `error` when they fail to authenticate or lack data they require to authenticate. For guidance on resolving errors from specific credential types, see the [troubleshooting guide](https://aka.ms/azsdk/go/identity/troubleshoot). + +For more details on handling specific Microsoft Entra errors, see the Microsoft Entra [error code documentation](https://learn.microsoft.com/entra/identity-platform/reference-error-codes). + +### Logging + +This module uses the classification-based logging implementation in `azcore`. To enable console logging for all SDK modules, set `AZURE_SDK_GO_LOGGING` to `all`. Use the `azcore/log` package to control log event output or to enable logs for `azidentity` only. For example: +```go +import azlog "github.com/Azure/azure-sdk-for-go/sdk/azcore/log" + +// print log output to stdout +azlog.SetListener(func(event azlog.Event, s string) { + fmt.Println(s) +}) + +// include only azidentity credential logs +azlog.SetEvents(azidentity.EventAuthentication) +``` + +Credentials log basic information only, such as `GetToken` success or failure and errors. These log entries don't contain authentication secrets but may contain sensitive information. + +## Next steps + +Client and management modules listed on the [Azure SDK releases page](https://azure.github.io/azure-sdk/releases/latest/go.html) support authenticating with `azidentity` credential types. You can learn more about using these libraries in their documentation, which is linked from the release page. + +## Provide Feedback + +If you encounter bugs or have suggestions, please +[open an issue](https://github.com/Azure/azure-sdk-for-go/issues). + +## Contributing + +This project welcomes contributions and suggestions. Most contributions require +you to agree to a Contributor License Agreement (CLA) declaring that you have +the right to, and actually do, grant us the rights to use your contribution. +For details, visit [https://cla.microsoft.com](https://cla.microsoft.com). + +When you submit a pull request, a CLA-bot will automatically determine whether +you need to provide a CLA and decorate the PR appropriately (e.g., label, +comment). Simply follow the instructions provided by the bot. You will only +need to do this once across all repos using our CLA. + +This project has adopted the +[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information, see the +[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) +or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any +additional questions or comments. + + +[ctc_overview]: https://aka.ms/azsdk/go/identity/credential-chains#chainedtokencredential-overview +[dac_overview]: https://aka.ms/azsdk/go/identity/credential-chains#defaultazurecredential-overview + + diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD new file mode 100644 index 000000000..8bdaf8165 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD @@ -0,0 +1,57 @@ +## Token caching in the Azure Identity client module + +Token caching helps apps: + +- Improve their resilience and performance. +- Reduce the number of requests sent to Microsoft Entra ID to obtain access tokens. +- Reduce the number of times users are prompted to authenticate. + +When an app needs to access a protected Azure resource, it typically needs to obtain an access token from Entra ID by sending an HTTP request and sometimes prompting a user to authenticate interactively. Credentials with caches (see [the below table](#credentials-supporting-token-caching) for a list) store access tokens either [in memory](#in-memory-token-caching) or, optionally, [on disk](#persistent-token-caching). These credentials return cached tokens whenever possible, to avoid unnecessary token requests or user interaction. Both cache implementations are safe for concurrent use. + +#### Caching can't be disabled + +Whether a credential caches tokens isn't configurable. If a credential has a cache of either kind, it requests a new token only when it can't provide one from its cache. Azure SDK service clients have an additional, independent layer of in-memory token caching, to prevent redundant token requests. This cache works with any credential type, even a custom implementation defined outside the Azure SDK, and can't be disabled. Disabling token caching is therefore impossible when using Azure SDK clients or most `azidentity` credential types. However, in-memory caches can be cleared by constructing new credential and client instances. + +### In-memory token caching + +Credential types that support caching store tokens in memory by default and require no configuration to do so. Each instance of these types has its own cache, and two credential instances never share an in-memory cache. + +### Persistent token caching + +Some credential types support opt-in persistent token caching (see [the below table](#credentials-supporting-token-caching) for a list). This feature enables credentials to store and retrieve tokens across process executions, so an application doesn't need to authenticate every time it runs. + +Persistent caches are encrypted at rest using a mechanism that depends on the operating system: + +| Operating system | Encryption facility | Limitations | +| ---------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Linux | kernel key retention service (keyctl) | Cache data is lost on system shutdown because kernel keys are stored in memory. Depending on kernel compile options, data may also be lost on logout, or storage may be impossible because the key retention service isn't available. | +| macOS | Keychain | Building requires cgo and native build tools. Keychain access requires a graphical session, so persistent caching isn't possible in a headless environment such as an SSH session (macOS as host). | +| Windows | Data Protection API (DPAPI) | No specific limitations. | + +Persistent caching requires encryption. When the required encryption facility is unuseable, or the application is running on an unsupported OS, the persistent cache constructor returns an error. This doesn't mean that authentication is impossible, only that credentials can't persist authentication data and the application will need to reauthenticate the next time it runs. See the package documentation for examples showing how to configure persistent caching and access cached data for [users][user_example] and [service principals][sp_example]. + +### Credentials supporting token caching + +The following table indicates the state of in-memory and persistent caching in each credential type. + +**Note:** in-memory caching is enabled by default for every type supporting it. Persistent token caching must be enabled explicitly. See the [package documentation][user_example] for an example showing how to do this for credential types authenticating users. For types that authenticate service principals, set the `Cache` field on the constructor's options as shown in [this example][sp_example]. + +| Credential | In-memory token caching | Persistent token caching | +| ------------------------------ | ------------------------------------------------------------------- | ------------------------ | +| `AzureCLICredential` | Not Supported | Not Supported | +| `AzureDeveloperCLICredential` | Not Supported | Not Supported | +| `AzurePowerShellCredential` | Not Supported | Not Supported | +| `AzurePipelinesCredential` | Supported | Supported | +| `ClientAssertionCredential` | Supported | Supported | +| `ClientCertificateCredential` | Supported | Supported | +| `ClientSecretCredential` | Supported | Supported | +| `DefaultAzureCredential` | Supported if the target credential in the default chain supports it | Not Supported | +| `DeviceCodeCredential` | Supported | Supported | +| `EnvironmentCredential` | Supported | Not Supported | +| `InteractiveBrowserCredential` | Supported | Supported | +| `ManagedIdentityCredential` | Supported | Not Supported | +| `OnBehalfOfCredential` | Supported | Not Supported | +| `WorkloadIdentityCredential` | Supported | Supported | + +[sp_example]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#example-package-PersistentServicePrincipalAuthentication +[user_example]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#example-package-PersistentUserAuthentication diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md new file mode 100644 index 000000000..517006a42 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md @@ -0,0 +1,278 @@ +# Troubleshoot Azure Identity authentication issues + +This troubleshooting guide covers failure investigation techniques, common errors for the credential types in the `azidentity` module, and mitigation steps to resolve these errors. + +## Table of contents + +- [Handle azidentity errors](#handle-azidentity-errors) + - [Permission issues](#permission-issues) +- [Find relevant information in errors](#find-relevant-information-in-errors) +- [Enable and configure logging](#enable-and-configure-logging) +- [Troubleshoot persistent token caching issues](#troubleshoot-persistent-token-caching-issues) +- [Troubleshoot AzureCLICredential authentication issues](#troubleshoot-azureclicredential-authentication-issues) +- [Troubleshoot AzureDeveloperCLICredential authentication issues](#troubleshoot-azuredeveloperclicredential-authentication-issues) +- [Troubleshoot AzurePipelinesCredential authentication issues](#troubleshoot-azurepipelinescredential-authentication-issues) +- [Troubleshoot AzurePowerShellCredential authentication issues](#troubleshoot-azurepowershellcredential-authentication-issues) +- [Troubleshoot ClientCertificateCredential authentication issues](#troubleshoot-clientcertificatecredential-authentication-issues) +- [Troubleshoot ClientSecretCredential authentication issues](#troubleshoot-clientsecretcredential-authentication-issues) +- [Troubleshoot DefaultAzureCredential authentication issues](#troubleshoot-defaultazurecredential-authentication-issues) +- [Troubleshoot EnvironmentCredential authentication issues](#troubleshoot-environmentcredential-authentication-issues) +- [Troubleshoot ManagedIdentityCredential authentication issues](#troubleshoot-managedidentitycredential-authentication-issues) + - [Azure App Service and Azure Functions managed identity](#azure-app-service-and-azure-functions-managed-identity) + - [Azure Virtual Machine managed identity](#azure-virtual-machine-managed-identity) +- [Troubleshoot WorkloadIdentityCredential authentication issues](#troubleshoot-workloadidentitycredential-authentication-issues) +- [Get additional help](#get-additional-help) + +## Handle azidentity errors + +Any service client method that makes a request to the service may return an error due to authentication failure. This is because the credential authenticates on the first call to the service and on any subsequent call that needs to refresh an access token. Authentication errors include a description of the failure and possibly an error message from Microsoft Entra ID. Depending on the application, these errors may or may not be recoverable. + +### Permission issues + +Service client errors with a status code of 401 or 403 often indicate that authentication succeeded but the caller doesn't have permission to access the specified API. Check the service documentation to determine which RBAC roles are needed for the request, and ensure the authenticated user or service principal has the appropriate role assignments. + +## Find relevant information in errors + +Authentication errors can include responses from Microsoft Entra ID and often contain information helpful in diagnosis. Consider the following error message: + +``` +ClientSecretCredential authentication failed +POST https://login.microsoftonline.com/3c631bb7-a9f7-4343-a5ba-a615913/oauth2/v2.0/token +-------------------------------------------------------------------------------- +RESPONSE 401 Unauthorized +-------------------------------------------------------------------------------- +{ + "error": "invalid_client", + "error_description": "AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app '86be4c01-505b-45e9-bfc0-9b825fd84'.\r\nTrace ID: 03da4b8e-5ffe-48ca-9754-aff4276f0100\r\nCorrelation ID: 7b12f9bb-2eef-42e3-ad75-eee69ec9088d\r\nTimestamp: 2022-03-02 18:25:26Z", + "error_codes": [ + 7000215 + ], + "timestamp": "2022-03-02 18:25:26Z", + "trace_id": "03da4b8e-5ffe-48ca-9754-aff4276f0100", + "correlation_id": "7b12f9bb-2eef-42e3-ad75-eee69ec9088d", + "error_uri": "https://login.microsoftonline.com/error?code=7000215" +} +-------------------------------------------------------------------------------- +``` + +This error contains several pieces of information: + +- __Failing Credential Type__: The type of credential that failed to authenticate. This can be helpful when diagnosing issues with chained credential types such as `DefaultAzureCredential` or `ChainedTokenCredential`. + +- __Microsoft Entra ID Error Code and Message__: The error code and message returned by Microsoft Entra ID. This can give insight into the specific reason the request failed. For instance, in this case authentication failed because the provided client secret is incorrect. [Microsoft Entra ID documentation](https://learn.microsoft.com/entra/identity-platform/reference-error-codes#aadsts-error-codes) has more information on AADSTS error codes. + +- __Correlation ID and Timestamp__: The correlation ID and timestamp identify the request in server-side logs. This information can be useful to support engineers diagnosing unexpected Microsoft Entra failures. + +### Enable and configure logging + +`azidentity` provides the same logging capabilities as the rest of the Azure SDK. The simplest way to see the logs to help debug authentication issues is to print credential logs to the console. +```go +import azlog "github.com/Azure/azure-sdk-for-go/sdk/azcore/log" + +// print log output to stdout +azlog.SetListener(func(event azlog.Event, s string) { + fmt.Println(s) +}) + +// include only azidentity credential logs +azlog.SetEvents(azidentity.EventAuthentication) +``` + + +## Troubleshoot DefaultAzureCredential authentication issues + +| Error |Description| Mitigation | +|---|---|---| +|"DefaultAzureCredential failed to acquire a token"|No credential in the `DefaultAzureCredential` chain provided a token|