package launcher_test import ( "context" "testing" "github.com/influxdata/influx-cli/v2/clients/backup" "github.com/influxdata/influx-cli/v2/clients/restore" "github.com/influxdata/influxdb/v2" "github.com/influxdata/influxdb/v2/cmd/influxd/launcher" "github.com/influxdata/influxdb/v2/kit/platform/errors" "github.com/stretchr/testify/require" "go.uber.org/zap" ) func TestBackupRestore_Full(t *testing.T) { t.Parallel() ctx := context.Background() backupDir := t.TempDir() // Boot a server, write some data, and take a backup. l1 := launcher.RunAndSetupNewLauncherOrFail(ctx, t, func(o *launcher.InfluxdOpts) { o.StoreType = "bolt" o.Testing = false o.LogLevel = zap.InfoLevel }) originalAuth := *l1.Auth l1.WritePointsOrFail(t, "m,k=v1 f=100i 946684800000000000\nm,k=v2 f=200i 946684800000000001") l1.BackupOrFail(t, ctx, backup.Params{Path: backupDir}) // Create a new bucket, write data into it (+ the old bucket), and take another backup. b1 := influxdb.Bucket{OrgID: l1.Org.ID, Name: "bucket2"} require.NoError(t, l1.BucketService(t).CreateBucket(ctx, &b1)) l1.WriteOrFail(t, &influxdb.OnboardingResults{ Org: l1.Org, Bucket: &b1, Auth: l1.Auth, }, "m,k=v1 f=100i 946684800000000005\nm,k=v2 f=200i 946684800000000006") l1.WritePointsOrFail(t, "m,k=v1 f=100i 946684800000000002\nm,k=v2 f=200i 946684800000000003") l1.BackupOrFail(t, ctx, backup.Params{Path: backupDir}) // Shut down the server. l1.ShutdownOrFail(t, ctx) // Boot up a second server, using a new auth token l2 := launcher.NewTestLauncher() l2.RunOrFail(t, ctx, func(o *launcher.InfluxdOpts) { o.StoreType = "bolt" o.Testing = false o.LogLevel = zap.InfoLevel }) defer l2.ShutdownOrFail(t, ctx) onboardReq := influxdb.OnboardingRequest{ User: "USER", Password: "PASSWORD", Org: "ORG", Bucket: "BUCKET", } onboardRes := l2.OnBoardOrFail(t, &onboardReq) l2.Org = onboardRes.Org l2.Bucket = onboardRes.Bucket l2.Auth = onboardRes.Auth // Create a second bucket, write data into it. b2 := influxdb.Bucket{OrgID: onboardRes.Org.ID, Name: "2bucket"} require.NoError(t, l2.BucketService(t).CreateBucket(ctx, &b2)) l2.WriteOrFail(t, &influxdb.OnboardingResults{ Org: onboardRes.Org, Bucket: &b2, Auth: onboardRes.Auth, }, "m,k=v5 f=100i 946684800000000005\nm,k=v7 f=200i 946684800000000006") // Perform a full restore from the previous backups. l2.RestoreOrFail(t, ctx, restore.Params{Path: backupDir, Full: true}) // A full restore also restores the original token l2.Auth = &originalAuth l2.ResetHTTPCLient() // Check that orgs and buckets were reset to match the original server's metadata. _, err := l2.OrgService(t).FindOrganizationByID(ctx, l2.Org.ID) require.Equal(t, errors.ENotFound, errors.ErrorCode(err)) rbkt1, err := l2.BucketService(t).FindBucket(ctx, influxdb.BucketFilter{OrganizationID: &l1.Org.ID, ID: &l1.Bucket.ID}) require.NoError(t, err) require.Equal(t, l1.Bucket.Name, rbkt1.Name) rbkt2, err := l2.BucketService(t).FindBucket(ctx, influxdb.BucketFilter{OrganizationID: &l1.Org.ID, ID: &b1.ID}) require.NoError(t, err) require.Equal(t, b1.Name, rbkt2.Name) _, err = l2.BucketService(t).FindBucket(ctx, influxdb.BucketFilter{OrganizationID: &l2.Org.ID, ID: &b2.ID}) require.Equal(t, errors.ENotFound, errors.ErrorCode(err)) // Check that data was restored to buckets. q1 := `from(bucket:"BUCKET") |> range(start:2000-01-01T00:00:00Z,stop:2000-01-02T00:00:00Z)` exp1 := `,result,table,_start,_stop,_time,_value,_field,_measurement,k` + "\r\n" + `,_result,0,2000-01-01T00:00:00Z,2000-01-02T00:00:00Z,2000-01-01T00:00:00Z,100,f,m,v1` + "\r\n" + `,_result,0,2000-01-01T00:00:00Z,2000-01-02T00:00:00Z,2000-01-01T00:00:00.000000002Z,100,f,m,v1` + "\r\n" + `,_result,1,2000-01-01T00:00:00Z,2000-01-02T00:00:00Z,2000-01-01T00:00:00.000000001Z,200,f,m,v2` + "\r\n" + `,_result,1,2000-01-01T00:00:00Z,2000-01-02T00:00:00Z,2000-01-01T00:00:00.000000003Z,200,f,m,v2` + "\r\n\r\n" res1 := l2.FluxQueryOrFail(t, l2.Org, l2.Auth.Token, q1) require.Equal(t, exp1, res1) q2 := `from(bucket:"bucket2") |> range(start:2000-01-01T00:00:00Z,stop:2000-01-02T00:00:00Z)` exp2 := `,result,table,_start,_stop,_time,_value,_field,_measurement,k` + "\r\n" + `,_result,0,2000-01-01T00:00:00Z,2000-01-02T00:00:00Z,2000-01-01T00:00:00.000000005Z,100,f,m,v1` + "\r\n" + `,_result,1,2000-01-01T00:00:00Z,2000-01-02T00:00:00Z,2000-01-01T00:00:00.000000006Z,200,f,m,v2` + "\r\n\r\n" res2 := l2.FluxQueryOrFail(t, l2.Org, l2.Auth.Token, q2) require.Equal(t, exp2, res2) } func TestBackupRestore_Partial(t *testing.T) { t.Parallel() ctx := context.Background() backupDir := t.TempDir() // Boot a server, write some data, and take a backup. l1 := launcher.RunAndSetupNewLauncherOrFail(ctx, t, func(o *launcher.InfluxdOpts) { o.StoreType = "bolt" o.Testing = false o.LogLevel = zap.InfoLevel }) l1.WritePointsOrFail(t, "m,k=v1 f=100i 946684800000000000\nm,k=v2 f=200i 946684800000000001") l1.BackupOrFail(t, ctx, backup.Params{Path: backupDir}) // Create a new bucket, write data into it (+ the old bucket), and take another backup. b1 := influxdb.Bucket{OrgID: l1.Org.ID, Name: "bucket2"} require.NoError(t, l1.BucketService(t).CreateBucket(ctx, &b1)) l1.WriteOrFail(t, &influxdb.OnboardingResults{ Org: l1.Org, Bucket: &b1, Auth: l1.Auth, }, "m,k=v1 f=100i 946684800000000005\nm,k=v2 f=200i 946684800000000006") l1.WritePointsOrFail(t, "m,k=v1 f=100i 946684800000000002\nm,k=v2 f=200i 946684800000000003") l1.BackupOrFail(t, ctx, backup.Params{Path: backupDir}) // Shut down the server. l1.ShutdownOrFail(t, ctx) // Boot up a second server. l2 := launcher.NewTestLauncher() l2.RunOrFail(t, ctx, func(o *launcher.InfluxdOpts) { o.StoreType = "bolt" o.Testing = false o.LogLevel = zap.InfoLevel }) defer l2.ShutdownOrFail(t, ctx) onboardReq := influxdb.OnboardingRequest{ User: "USER", Password: "PASSWORD", Org: "ORG2", Bucket: "BUCKET", } onboardRes := l2.OnBoardOrFail(t, &onboardReq) l2.Org = onboardRes.Org l2.Bucket = onboardRes.Bucket l2.Auth = onboardRes.Auth // Create a second bucket, write data into it. b2 := influxdb.Bucket{OrgID: onboardRes.Org.ID, Name: "2bucket"} require.NoError(t, l2.BucketService(t).CreateBucket(ctx, &b2)) l2.WriteOrFail(t, &influxdb.OnboardingResults{ Org: onboardRes.Org, Bucket: &b2, Auth: onboardRes.Auth, }, "m,k=v5 f=100i 946684800000000005\nm,k=v7 f=200i 946684800000000006") // Perform a partial restore from the previous backups. l2.RestoreOrFail(t, ctx, restore.Params{Path: backupDir}) // Check that buckets from the 1st launcher were restored to the new server. rbkt1, err := l2.BucketService(t).FindBucket(ctx, influxdb.BucketFilter{Org: &l1.Org.Name, Name: &l1.Bucket.Name}) require.NoError(t, err) require.Equal(t, l1.Bucket.Name, rbkt1.Name) rbkt2, err := l2.BucketService(t).FindBucket(ctx, influxdb.BucketFilter{Org: &l1.Org.Name, Name: &b1.Name}) require.NoError(t, err) require.Equal(t, b1.Name, rbkt2.Name) // Check that data was restored to buckets. q1 := `from(bucket:"BUCKET") |> range(start:2000-01-01T00:00:00Z,stop:2000-01-02T00:00:00Z)` exp1 := `,result,table,_start,_stop,_time,_value,_field,_measurement,k` + "\r\n" + `,_result,0,2000-01-01T00:00:00Z,2000-01-02T00:00:00Z,2000-01-01T00:00:00Z,100,f,m,v1` + "\r\n" + `,_result,0,2000-01-01T00:00:00Z,2000-01-02T00:00:00Z,2000-01-01T00:00:00.000000002Z,100,f,m,v1` + "\r\n" + `,_result,1,2000-01-01T00:00:00Z,2000-01-02T00:00:00Z,2000-01-01T00:00:00.000000001Z,200,f,m,v2` + "\r\n" + `,_result,1,2000-01-01T00:00:00Z,2000-01-02T00:00:00Z,2000-01-01T00:00:00.000000003Z,200,f,m,v2` + "\r\n\r\n" res1 := l2.FluxQueryOrFail(t, l1.Org, l2.Auth.Token, q1) require.Equal(t, exp1, res1) q2 := `from(bucket:"bucket2") |> range(start:2000-01-01T00:00:00Z,stop:2000-01-02T00:00:00Z)` exp2 := `,result,table,_start,_stop,_time,_value,_field,_measurement,k` + "\r\n" + `,_result,0,2000-01-01T00:00:00Z,2000-01-02T00:00:00Z,2000-01-01T00:00:00.000000005Z,100,f,m,v1` + "\r\n" + `,_result,1,2000-01-01T00:00:00Z,2000-01-02T00:00:00Z,2000-01-01T00:00:00.000000006Z,200,f,m,v2` + "\r\n\r\n" res2 := l2.FluxQueryOrFail(t, l1.Org, l2.Auth.Token, q2) require.Equal(t, exp2, res2) // Check that the 2nd launcher's buckets weren't touched. newBucket1, err := l2.BucketService(t).FindBucket(ctx, influxdb.BucketFilter{OrganizationID: &l2.Org.ID, ID: &l2.Bucket.ID}) require.NoError(t, err) require.Equal(t, l2.Bucket.Name, newBucket1.Name) newBucket2, err := l2.BucketService(t).FindBucket(ctx, influxdb.BucketFilter{OrganizationID: &l2.Org.ID, ID: &b2.ID}) require.NoError(t, err) require.Equal(t, b2.Name, newBucket2.Name) q3 := `from(bucket:"2bucket") |> range(start:2000-01-01T00:00:00Z,stop:2000-01-02T00:00:00Z)` exp3 := `,result,table,_start,_stop,_time,_value,_field,_measurement,k` + "\r\n" + `,_result,0,2000-01-01T00:00:00Z,2000-01-02T00:00:00Z,2000-01-01T00:00:00.000000005Z,100,f,m,v5` + "\r\n" + `,_result,1,2000-01-01T00:00:00Z,2000-01-02T00:00:00Z,2000-01-01T00:00:00.000000006Z,200,f,m,v7` + "\r\n\r\n" res3 := l2.FluxQueryOrFail(t, l2.Org, l2.Auth.Token, q3) require.Equal(t, exp3, res3) }