Live data from Hacker News

In praise of –dry-run

henrikwarne.com

131–140 of 175 posts

Re: In praise of –dry-run

#131
post #109

Funny, I recalled a tool called "molly-guard" which solves the problem when you want to reboot a Unix server, but can be on the wrong one. It asks to type the server name. Anybody who rebooted a wrong server can say that this tool is brilliant. Like "--dry-run" but for "reboot."

These kind of obstacles don't work for any action that the user does repeatedly. Dialogs that pop up and ask "Are you sure you want to delete ...?" -> users just automatically click yes, because they already did that the last 10 times and just want to get on with their work. Logged in to server "alpha" instead of "delta" because you thought that's the right one. Tool asks you to write the server name. You type "alpha…

> Github ask you to confirm the repo name before deleting by typing it into a text field. User looks at what the repo name is and types it without thinking. Or, like lazy me, mark and drag the displayed name into the field, so you don't even have to type.

Pretty easy to solve this sort of stuff with timers: "Sure, the repo will be deleted in . Press here to abort: ."

Or have the timers on the backend and just show the user an undo button.

Re: In praise of –dry-run

#132
post #33

What if the tool required an "un-safeword" to do destructive things? "Do you really want to 'rm -rf /'? Type 'fiberglass' to proceed."

Like tarsnap's --nuke command: --nuke Delete all of the archives stored. To protect against accidental data loss, tarsnap will ask you to type the text "No Tomorrow" when using the --nuke command.

Probably inspired by Vinum's "NO FUTURE" for destructive operations. (Vinum was a raid system used on older versions of FreeBSD.)

Re: In praise of –dry-run

#133
post #84

If you're interacting with stateful systems (which you usually are with this kind of command), --dry-run can still have a race condition. The tool tells you what it would do in the current situation, you take a look and confirm that that's alright. Then you run it again without --dry-run, in a potentially different situation. That's why I prefer Terraform's approach of having a "plan" mode. It doesn't just tell you w…

>That's why I prefer Terraform's approach of having a "plan" mode. It doesn't just tell you what it would do but does so in the form of a plan it can later execute programmatically. Then, if any of the assumptions made during planning have changed, it can abort and roll back.

Not to take anything away from your comment but just to add a related story... the previous big AWS outage had an unforeseen race condition between their DNS planner vs DNS executor:

>[...] Right before this event started, one DNS Enactor experienced unusually high delays needing to retry its update on several of the DNS endpoints. As it was slowly working through the endpoints, several other things were also happening. First, the DNS Planner continued to run and produced many newer generations of plans. Second, one of the other DNS Enactors then began applying one of the newer plans and rapidly progressed through all of the endpoints. The timing of these events triggered the latent race condition. When the second Enactor (applying the newest plan) completed its endpoint updates, it then invoked the plan clean-up process, which identifies plans that are significantly older than the one it just applied and deletes them. At the same time that this clean-up process was invoked, the first Enactor (which had been unusually delayed) applied its much older plan to the regional DDB endpoint, overwriting the newer plan. The check that was made at the start of the plan application process, which ensures that the plan is newer than the previously applied plan, was stale by this time due to the unusually high delays in Enactor processing. [...]

previous HN thread: https://news.ycombinator.com/item?id=45677139

Re: In praise of –dry-run

#134
post #131

Earlier quoted context omitted.

These kind of obstacles don't work for any action that the user does repeatedly. Dialogs that pop up and ask "Are you sure you want to delete ...?" -> users just automatically click yes, because they already did that the last 10 times and just want to get on with their work. Logged in to server "alpha" instead of "delta" because you thought that's the right one. Tool asks you to write the server name. You type "alpha…

> Github ask you to confirm the repo name before deleting by typing it into a text field. User looks at what the repo name is and types it without thinking. Or, like lazy me, mark and drag the displayed name into the field, so you don't even have to type. Pretty easy to solve this sort of stuff with timers: "Sure, the repo will be deleted in . Press here to abort: ." Or have the timers on the backend and just show th…

[deleted]

Re: In praise of –dry-run

#135
A while ago when I was working with PowerShell a lot, I got spoiled by the easy inclusion of `-DryRun` flags in all my scripts.

Nowadays I still use the technique for a lot of the tools I make. I typically do a Terraform-like approach: create a plan, validate the plan, render the plan to the user, exit early if we're in dry-run mode, and apply the plan as the final step. Whether dry-run is enabled by default depends on the risk of the operations and who will be using the tool.

This makes it exceedingly clear what actions the tool will do. Plus it has the added benefit of being able to split the plan and apply steps into two separate steps. For example, you can create a plan, serialize it to JSON, store it (e.g. in VCS, Jira ticket, whatever) then apply it during a change window.

  plan = createPlan()
  print(plan.string())
  if (dryRun){
   return
  }
  
  plan.apply()

Re: In praise of –dry-run

#136
post #84

If you're interacting with stateful systems (which you usually are with this kind of command), --dry-run can still have a race condition. The tool tells you what it would do in the current situation, you take a look and confirm that that's alright. Then you run it again without --dry-run, in a potentially different situation. That's why I prefer Terraform's approach of having a "plan" mode. It doesn't just tell you w…

And just like that, you find yourself implementing a compiler (specs to plan) and a virtual machine (plan to actions)!

This is why I think things like devops benefit from the traditional computer science education. Once you see the pattern, whatever project you were assigned looks like something you've done before. And your users will appreciate the care and attention.

Re: In praise of –dry-run

#138
post #73

I like this pattern a lot, but it's important that the code in the dry path is representative. I've been bitten a few too many times by dry code that just runs `print("would have updated ID: 123")`, but not actually running most of the code in the hot path. Then when I run it for real, some of the prep for the write operation has a bug / error, so my dry run didn't actually reveal much to me. Put another way: your dr…

This is why I end up creating an interface for the calls that perform modifications. Then I have one implementation that logs and one implementation that does the actual work. I end up with the output being as representative as possible as to what would happen. I also feel a lot more comfortable that a dry run truly won't write anything when the only class that could ever actually write anything is not even instantiated in dry run mode. I don't get that same comfort when there's a ton of branches sprinkled throughout checking for a dry run flag.

Re: In praise of –dry-run

#139
post #102

I would love to have this available in git. I know if you make mistakes you can use the reflog, but if you need 5 tries to get something right reading the reflog quickly becomes impossible. Plus there are operations, like rebase or merge, that feel the need to make 50 entries in the reflog. I've resorted to copying the entire directory (including the .git part) and then trying on the copy. The issue is that I'm worki…

Consider using work trees. They have separate reflogs, you'd still get separate directories, but less duplication.

Re: In praise of –dry-run

#140
post #118

Earlier quoted context omitted.

And just like that, you find yourself implementing a compiler (specs to plan) and a virtual machine (plan to actions)!

I think you're already doing that? The only thing that's added is serializing the plan to a file and then deserializing it to make the changes.

Yeah any time you're translating "user args" and "system state" to actions + execution and supporting a "dry run" preview it seems like you only really have two options: the "ad-hoc quick and dirty informal implementation", or the "let's actually separate the planning and assumption checking and state checking from the execution" design.
Post reply on HN