Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DATA-930] Add support for data deletion by filter to the CLI #1667

Merged
merged 14 commits into from
Dec 22, 2022

Conversation

tahiyasalam
Copy link
Member

@tahiyasalam tahiyasalam commented Dec 13, 2022

  • Implements deletion through the cli tool

This can be run locally by doing the following:

  • checkout this pr locally
  • run go build -o ~/go/bin/viam cli/cmd/main.go to build the cli tool
  • use the command viam data delete --data_type binary --org_ids [YOUR-ORG-ID] --start 2022-12-21T15:49:08Z

@viambot viambot added the safe to test This pull request is marked safe to test from a trusted zone label Dec 13, 2022
@tahiyasalam
Copy link
Member Author

I still need to set up a local testing environment, but I wanted to send out for logic check

Copy link
Contributor

@agreenb agreenb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, thanks for adding this so quickly! Some minor comments.

return errors.Errorf("type must be binary or tabular, got %s", c.String("type"))
}

filter := &datapb.Filter{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the following logic on lines 876-933 is shared between this data and deletion commands, would suggest extracting into a helper method createDataFilter(filter *datapb.Filter) error

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great suggestion, done!

cli/cmd/main.go Outdated
@@ -296,6 +296,87 @@ func main() {
},
Action: DataCommand,
},
{
Name: "delete",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd lean towards calling this delete-data or deletedata but also nice to have single word commands. Getting another opinion @AaronCasas

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. I definitely think that this and the export command should be consistent in the sense that if this is data delete, that should be data export/download/whatever, and if this is just delete, that should just be export/download/whatever. I think I'd be partial towards the former (viam data <action) because I can definitely foresee a future where there are other delete operations we expose through the CLI (e.g. delete a robot).

Long winded way of saying: I'd vote data delete and changing data to data export or data download

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to consistency and good suggestion, as solely passing --data isn't descriptive as we add more functionality to the CLI. I'd set this up with data as the main command and export and delete as the subcommands:

https://stackoverflow.com/a/54900733

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to using subcommands, especially since we have so many flags here that'll all be shared

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! Added as a subcommand

cli/cmd/main.go Outdated
dataType := c.String(dataFlagDataType)
switch dataType {
case dataTypeBinary:
if err := client.BinaryData(c.String(dataFlagDestination), filter); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DeleteBinaryData

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, copy & paste mistake

cli/cmd/main.go Outdated
return err
}
case dataTypeTabular:
if err := client.BinaryData(c.String(dataFlagDestination), filter); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DeleteTabularData

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, copy & paste mistake

cli/delete.go Outdated
)

// DeleteBinaryData deletes binary data matching filter.
func (c *AppClient) DeleteBinaryData(dst string, filter *datapb.Filter) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can remove dst

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

cli/delete.go Outdated
status := resp.GetResult().GetStatus()

switch status {
case datapb.Status_STATUS_PARTIAL_SUCCESS:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can still have deleted some messages with a partial successes, so would still instead the deletedCount.
I think this section could be:

if status == datapb.Status_STATUS_PARTIAL_SUCCESS {
    fmt.Fprint(c.c.App.Writer, "errors", resp.GetResult().GetMessage())
}
fmt.Fprintf(c.c.App.Writer, "deleted %d files", deletedCount)
return nil

Same for tabular

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true, done!

cli/delete.go Outdated
return nil
}

func (c *AppClient) sendDeleteBinaryDataByFilterRequest(filter *datapb.Filter) (*datapb.DeleteBinaryDataByFilterResponse, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these two helper functions aren't adding additional logic and are quite short as-is, worth keeping the requests directly inline with the code above. Gives the benefit of readability above without having to redirect to what the helper functions do.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 15, 2022
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 15, 2022
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 15, 2022
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 15, 2022

dataType := c.String(dataFlagDataType)
switch dataType {
case dataTypeBinary:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AaronCasas I think this is showing up as something that is added in this PR since I re-arranged into the helper function. I believe this is fine, but can you just double check that this is as intended?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah this is because your createDataFilter should stop at

if start != nil || end != nil {
		filter.Interval = &datapb.CaptureInterval{
			Start: start,
			End:   end,
		}
	}

But from copying over too much, it continues with client, err := rdkcli.NewAppClient and the rest of this client.BinaryData code. If you remove that, that'll fix the helper and should show a normal diff in GH.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh thank you! I missed it

cli/delete.go Outdated
if status == datapb.Status_STATUS_PARTIAL_SUCCESS {
fmt.Fprint(c.c.App.Writer, "received errors when deleting objects\n", resp.GetResult().GetMessage())
}
fmt.Fprintf(c.c.App.Writer, "deleted %d files", deletedCount)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: deleted % datapoints

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 15, 2022
Copy link
Contributor

@AaronCasas AaronCasas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple small suggestions!

cli/cmd/main.go Outdated
@@ -712,6 +793,70 @@ func DataCommand(c *cli.Context) error {
}

filter := &datapb.Filter{}
if err := createDataFilter(c, filter); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in general it's better to return outputs* than modify inputs in place, so would suggest removing the filter parameter and just returning it instead:

filter, err := createDataFilter(c)

*A few reasons:

  • If we modify an input, then we introduce a whole class of possible cases: what if the input is X/Y/Z/any variation here? This adds some complexity both because some of those inputs may be completely invalid (so require validation inside the function), and because it basically makes the "output" (in this case the implicit output being that modified input) a function of both the input state and the function implementation: instead of being able to treat the function like a black box that can be understood based solely on its name/signature/etc, a reader has to understand the initial input, the function, and how those two work together. Obviously this is super trivial in this case because the input is always the empty filter, but it leaves it open to these issues if that were to change in the future.
  • The input is always the same (empty filter), so there's no need for the caller to need to provide it (and think about what they should provide/know it should be empty)

Copy link
Member Author

@tahiyasalam tahiyasalam Dec 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

cli/cmd/main.go Outdated

// DeleteCommand runs the command for deleting data from the Viam cloud.
func DeleteCommand(c *cli.Context) error {
if c.String(dataFlagDataType) != dataTypeBinary && c.String(dataFlagDataType) != dataTypeTabular {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you pull this into some validateDataType that returns the below error since it's now being used in multiple places?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, with the switch below doing the same validation, I think this can be removed entirely. I think this error message is more informative though, so would suggest replacing that one with this one

Copy link
Member Author

@tahiyasalam tahiyasalam Dec 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, lmk if this implementation makes sense to you

cli/cmd/main.go Outdated
}

func createDataFilter(c *cli.Context, filter *datapb.Filter) error {
if c.String(dataFlagDataType) != dataTypeBinary && c.String(dataFlagDataType) != dataTypeTabular {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this validation makes sense to include somewhere outside of this function, since it isn't directly filter related (in the sense that I think it might be appropriate to include if it was validating something needed to build the filter, but the dataFlagDataType isn't otherwise used in here)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

related to above

@tahiyasalam tahiyasalam marked this pull request as ready for review December 21, 2022 16:14
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 21, 2022
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 21, 2022
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 21, 2022
@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 21, 2022
Copy link
Contributor

@agreenb agreenb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, just one nit. Thanks for adding and reorganizing, excited about introducing subcommands 🚀🚀

Request that before submitting, you run local CLI tests that both deletion and data export work for both binary and tabular data. Thanks for updating the PR description to include how you ran deletion on binary!

cli/cmd/main.go Outdated
@@ -705,13 +792,75 @@ func main() {
}
}

func validateDataType(c *cli.Context) (string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[supernit] I think since we're already switching between data types below, it makes sense to keep the validation directly inline like you previously had and return the "type must be binary or tabular, got:" in the default case. A few reasons:

  1. I think when the logic is simple enough, it's preferable to keep validations together with use cases for increased readability.
    This differs from our filter validation in app where there's various combinations of invalid filters and more complicated query inference/population, but that's already created some issues of "how do I know in this function that I can access index 0? oh, I checked than len(arr) > 0 in the validate function"
  2. As we add more API calls, they may be specific to binary (e.g. add/delete tags to existing images)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 21, 2022
cli/cmd/main.go Outdated
// DeleteCommand runs the command for deleting data from the Viam cloud.
func DeleteCommand(c *cli.Context) error {
dataType := c.String(dataFlagDataType)
if dataType != dataTypeBinary && dataType != dataTypeTabular {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would still keep this as a switch case on dataType below in both command functions to avoid redundancy — we're doing a quick operation of creating a data filter and initializing an AppClient struct beforehand so ok wait to validate until after.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sense, done

@viambot viambot added safe to test This pull request is marked safe to test from a trusted zone and removed safe to test This pull request is marked safe to test from a trusted zone labels Dec 21, 2022
@github-actions
Copy link
Contributor

Code Coverage

Package Line Rate Delta Health
go.viam.com/rdk/components/arm 56% 0.00%
go.viam.com/rdk/components/arm/universalrobots 13% 0.00%
go.viam.com/rdk/components/arm/xarm 2% 0.00%
go.viam.com/rdk/components/arm/yahboom 7% 0.00%
go.viam.com/rdk/components/audioinput 55% 0.00%
go.viam.com/rdk/components/base 63% 0.00%
go.viam.com/rdk/components/base/agilex 62% 0.00%
go.viam.com/rdk/components/base/boat 41% 0.00%
go.viam.com/rdk/components/base/wheeled 76% 0.00%
go.viam.com/rdk/components/board 68% 0.00%
go.viam.com/rdk/components/board/arduino 10% 0.00%
go.viam.com/rdk/components/board/commonsysfs 47% 0.00%
go.viam.com/rdk/components/board/fake 38% 0.00%
go.viam.com/rdk/components/board/numato 19% 0.00%
go.viam.com/rdk/components/board/pi 50% 0.00%
go.viam.com/rdk/components/camera 65% 0.00%
go.viam.com/rdk/components/camera/align 64% +0.48%
go.viam.com/rdk/components/camera/fake 67% 0.00%
go.viam.com/rdk/components/camera/ffmpeg 77% 0.00%
go.viam.com/rdk/components/camera/transformpipeline 79% 0.00%
go.viam.com/rdk/components/camera/videosource 49% -0.63%
go.viam.com/rdk/components/encoder/fake 77% 0.00%
go.viam.com/rdk/components/gantry 60% 0.00%
go.viam.com/rdk/components/gantry/multiaxis 84% 0.00%
go.viam.com/rdk/components/gantry/oneaxis 86% 0.00%
go.viam.com/rdk/components/generic 83% 0.00%
go.viam.com/rdk/components/gripper 68% 0.00%
go.viam.com/rdk/components/input 87% 0.00%
go.viam.com/rdk/components/input/gpio 84% 0.00%
go.viam.com/rdk/components/motor 77% 0.00%
go.viam.com/rdk/components/motor/dimensionengineering 63% 0.00%
go.viam.com/rdk/components/motor/dmc4000 69% 0.00%
go.viam.com/rdk/components/motor/fake 57% 0.00%
go.viam.com/rdk/components/motor/gpio 61% -2.16%
go.viam.com/rdk/components/motor/gpiostepper 57% 0.00%
go.viam.com/rdk/components/motor/tmcstepper 62% 0.00%
go.viam.com/rdk/components/movementsensor 75% 0.00%
go.viam.com/rdk/components/movementsensor/cameramono 40% 0.00%
go.viam.com/rdk/components/movementsensor/gpsnmea 37% 0.00%
go.viam.com/rdk/components/movementsensor/gpsrtk 28% 0.00%
go.viam.com/rdk/components/posetracker 86% 0.00%
go.viam.com/rdk/components/sensor 86% 0.00%
go.viam.com/rdk/components/sensor/ultrasonic 34% 0.00%
go.viam.com/rdk/components/servo 68% 0.00%
go.viam.com/rdk/components/servo/gpio 71% 0.00%
go.viam.com/rdk/config 76% 0.00%
go.viam.com/rdk/control 57% 0.00%
go.viam.com/rdk/data 77% 0.00%
go.viam.com/rdk/examples/customresources/demos/complexmodule 0% 0.00%
go.viam.com/rdk/examples/customresources/demos/remoteserver 0% 0.00%
go.viam.com/rdk/grpc 25% 0.00%
go.viam.com/rdk/ml 67% 0.00%
go.viam.com/rdk/ml/inference 70% 0.00%
go.viam.com/rdk/module 64% 0.00%
go.viam.com/rdk/module/modmanager 79% 0.00%
go.viam.com/rdk/motionplan 59% -8.62%
go.viam.com/rdk/octree 98% 0.00%
go.viam.com/rdk/operation 82% 0.00%
go.viam.com/rdk/pointcloud 72% 0.00%
go.viam.com/rdk/protoutils 59% 0.00%
go.viam.com/rdk/referenceframe 70% 0.00%
go.viam.com/rdk/registry 89% 0.00%
go.viam.com/rdk/resource 84% 0.00%
go.viam.com/rdk/rimage 78% 0.00%
go.viam.com/rdk/rimage/depthadapter 94% 0.00%
go.viam.com/rdk/rimage/transform 73% 0.00%
go.viam.com/rdk/rimage/transform/cmd/extrinsic_calibration 67% 0.00%
go.viam.com/rdk/robot 85% -0.95%
go.viam.com/rdk/robot/client 82% 0.00%
go.viam.com/rdk/robot/framesystem 68% 0.00%
go.viam.com/rdk/robot/impl 81% 0.00%
go.viam.com/rdk/robot/server 59% +0.63%
go.viam.com/rdk/robot/web 62% 0.00%
go.viam.com/rdk/robot/web/stream 87% 0.00%
go.viam.com/rdk/services/armremotecontrol 71% 0.00%
go.viam.com/rdk/services/armremotecontrol/builtin 52% 0.00%
go.viam.com/rdk/services/baseremotecontrol 71% 0.00%
go.viam.com/rdk/services/baseremotecontrol/builtin 79% 0.00%
go.viam.com/rdk/services/datamanager 65% 0.00%
go.viam.com/rdk/services/datamanager/builtin 80% 0.00%
go.viam.com/rdk/services/datamanager/datacapture 21% 0.00%
go.viam.com/rdk/services/datamanager/datasync 72% 0.00%
go.viam.com/rdk/services/motion 63% 0.00%
go.viam.com/rdk/services/motion/builtin 88% 0.00%
go.viam.com/rdk/services/navigation 53% 0.00%
go.viam.com/rdk/services/sensors 77% 0.00%
go.viam.com/rdk/services/sensors/builtin 97% 0.00%
go.viam.com/rdk/services/shell 14% 0.00%
go.viam.com/rdk/services/slam 84% 0.00%
go.viam.com/rdk/services/slam/builtin 72% 0.00%
go.viam.com/rdk/services/vision 80% 0.00%
go.viam.com/rdk/services/vision/builtin 74% 0.00%
go.viam.com/rdk/session 97% 0.00%
go.viam.com/rdk/spatialmath 83% 0.00%
go.viam.com/rdk/subtype 92% 0.00%
go.viam.com/rdk/utils 72% +0.18%
go.viam.com/rdk/vision 26% 0.00%
go.viam.com/rdk/vision/chess 80% 0.00%
go.viam.com/rdk/vision/delaunay 87% 0.00%
go.viam.com/rdk/vision/keypoints 92% 0.00%
go.viam.com/rdk/vision/objectdetection 82% 0.00%
go.viam.com/rdk/vision/odometry 60% 0.00%
go.viam.com/rdk/vision/odometry/cmd 0% 0.00%
go.viam.com/rdk/vision/segmentation 49% 0.00%
go.viam.com/rdk/web/server 26% 0.00%
Summary 66% (20817 / 31709) -0.57%

Copy link
Contributor

@agreenb agreenb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

Copy link
Contributor

@AaronCasas AaronCasas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! 🚀

@tahiyasalam tahiyasalam merged commit c14a8bb into viamrobotics:main Dec 22, 2022
@tahiyasalam tahiyasalam deleted the delete-cli branch December 22, 2022 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
safe to test This pull request is marked safe to test from a trusted zone
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants