From 643386f026cb228aac24bf97e7f74b13ce5d0f20 Mon Sep 17 00:00:00 2001 From: Drew Stinnett Date: Tue, 5 Sep 2023 13:57:23 -0400 Subject: [PATCH] rc: Add operations/settier to API --- fs/operations/operations.go | 14 ++++++++++ fs/operations/rc.go | 24 ++++++++++++++++ fs/operations/rc_test.go | 55 +++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/fs/operations/operations.go b/fs/operations/operations.go index c48ca4169..441c30971 100644 --- a/fs/operations/operations.go +++ b/fs/operations/operations.go @@ -2091,6 +2091,20 @@ func SetTier(ctx context.Context, fsrc fs.Fs, tier string) error { }) } +// SetTierFile changes tier of a single file in remote +func SetTierFile(ctx context.Context, o fs.Object, tier string) error { + do, ok := o.(fs.SetTierer) + if !ok { + return errors.New("remote object does not implement SetTier") + } + err := do.SetTier(tier) + if err != nil { + fs.Errorf(o, "Failed to do SetTier, %v", err) + return err + } + return nil +} + // TouchDir touches every file in directory with time t func TouchDir(ctx context.Context, f fs.Fs, remote string, t time.Time, recursive bool) error { return walk.ListR(ctx, f, remote, false, ConfigMaxDepth(ctx, recursive), walk.ListObjects, func(entries fs.DirEntries) error { diff --git a/fs/operations/rc.go b/fs/operations/rc.go index 66804ab00..bff50dccd 100644 --- a/fs/operations/rc.go +++ b/fs/operations/rc.go @@ -211,6 +211,8 @@ func init() { {name: "copyurl", title: "Copy the URL to the object", help: "- url - string, URL to read from\n - autoFilename - boolean, set to true to retrieve destination file name from url\n"}, {name: "uploadfile", title: "Upload file using multiform/form-data", help: "- each part in body represents a file to be uploaded\n", needsRequest: true}, {name: "cleanup", title: "Remove trashed files in the remote or path", noRemote: true}, + {name: "settier", title: "Changes storage tier or class on all files in the path", noRemote: true}, + {name: "settierfile", title: "Changes storage tier or class on the single file pointed to"}, } { op := op remote := "- remote - a path within that remote e.g. \"dir\"\n" @@ -318,6 +320,28 @@ func rcSingleCommand(ctx context.Context, in rc.Params, name string, noRemote bo return nil, nil case "cleanup": return nil, CleanUp(ctx, f) + case "settier": + if !f.Features().SetTier { + return nil, fmt.Errorf("remote %s does not support settier", f.Name()) + } + tier, err := in.GetString("tier") + if err != nil { + return nil, err + } + return nil, SetTier(ctx, f, tier) + case "settierfile": + if !f.Features().SetTier { + return nil, fmt.Errorf("remote %s does not support settier", f.Name()) + } + tier, err := in.GetString("tier") + if err != nil { + return nil, err + } + o, err := f.NewObject(ctx, remote) + if err != nil { + return nil, err + } + return nil, SetTierFile(ctx, o, tier) } panic("unknown rcSingleCommand type") } diff --git a/fs/operations/rc_test.go b/fs/operations/rc_test.go index ebe0994c1..b550cf85a 100644 --- a/fs/operations/rc_test.go +++ b/fs/operations/rc_test.go @@ -307,6 +307,61 @@ func TestRcStat(t *testing.T) { }) } +// operations/settier: Set the storage tier of a fs +func TestRcSetTier(t *testing.T) { + ctx := context.Background() + r, call := rcNewRun(t, "operations/settier") + if !r.Fremote.Features().SetTier { + t.Skip("settier not supported") + } + file1 := r.WriteObject(context.Background(), "file1", "file1 contents", t1) + r.CheckRemoteItems(t, file1) + + // Because we don't know what the current tier options here are, let's + // just get the current tier, and re-use that + o, err := r.Fremote.NewObject(ctx, file1.Path) + require.NoError(t, err) + trr, ok := o.(fs.GetTierer) + require.True(t, ok) + ctier := trr.GetTier() + in := rc.Params{ + "fs": r.FremoteName, + "tier": ctier, + } + out, err := call.Fn(context.Background(), in) + require.NoError(t, err) + assert.Equal(t, rc.Params(nil), out) + +} + +// operations/settier: Set the storage tier of a file +func TestRcSetTierFile(t *testing.T) { + ctx := context.Background() + r, call := rcNewRun(t, "operations/settierfile") + if !r.Fremote.Features().SetTier { + t.Skip("settier not supported") + } + file1 := r.WriteObject(context.Background(), "file1", "file1 contents", t1) + r.CheckRemoteItems(t, file1) + + // Because we don't know what the current tier options here are, let's + // just get the current tier, and re-use that + o, err := r.Fremote.NewObject(ctx, file1.Path) + require.NoError(t, err) + trr, ok := o.(fs.GetTierer) + require.True(t, ok) + ctier := trr.GetTier() + in := rc.Params{ + "fs": r.FremoteName, + "remote": "file1", + "tier": ctier, + } + out, err := call.Fn(context.Background(), in) + require.NoError(t, err) + assert.Equal(t, rc.Params(nil), out) + +} + // operations/mkdir: Make a destination directory or container func TestRcMkdir(t *testing.T) { ctx := context.Background()