Live data from Hacker News

In praise of –dry-run

henrikwarne.com

141–150 of 175 posts

Re: In praise of –dry-run

#141
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…

Totally agree, and this is covered in an (identically named?) Google Research blog [1].

Just last week I was writing a demo-focused Python file called `safetykit.py`, which has its first demo as this:

    def praise_dryrun(dryrun: bool = True) -> None:
        ...
The snippet which demonstrates the plan-then-execute pattern I have is this:

    def gather(paths):
        files = []
        for pattern in paths:
            files.extend(glob.glob(pattern))
        return files

    def execute(files):
        for f in files:
            os.remove(f)

    files = gather([os.path.join(tmp_dir, "*.txt")])
    if dryrun:
        print(f"Would remove: {files}")
    else:
        execute(files)
I introduced dry-run at my company and I've been happy to see it spread throughout the codebase, because it's a coding practice that more than pays for itself.

[1] https://www.gresearch.com/news/in-praise-of-dry-run/

Re: In praise of –dry-run

#142

Earlier quoted context omitted.

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

> And just like that, you find yourself implementing a compiler (specs to plan) and a virtual machine (plan to actions)! Not just any compiler, but a non-typesafe, ad-hoc, informally specified grammar with a bunch of unspecified or under-specified behaviour. Not sure if we can call this a win :-)

Greenspun's tenth rule in action!

Re: In praise of –dry-run

#143

Earlier quoted context omitted.

Just my two cents - but a general purpose language is going to need to be coupled with design patterns in order to be useful for different tasks. I'm using MVC design patterns for some codebases, I'm using DDD plus Event sourcing and Event Driven for others. I suspect that you are thinking of a small subset of design patterns (eg. Gang of Four derived patterns like Visitor, Strategy, or Iterator )

> I'm using MVC design patterns for some codebases, I'm using DDD plus Event sourcing and Event Driven for others. All examples of OO nonsense. There is only one pattern you need (functions) (tongue-in-cheek): https://fsharpforfunandprofit.com/fppatterns/ Edit: Also consider using the ELM architecture instead of MVC: https://guide.elm-lang.org/architecture/

I typically reach for Go when I am building things, bubbletea, a TUI library uses the Elm architecture and enforces it on people using it.

Did not like, Won't use again.

MVC is well understood and works perfectly in my experience.

edit:

Even though you were tongue in cheek about F# - this stood out on the page

> The functional programming community has design patterns and principles as well.

Re: In praise of –dry-run

#144
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…

I had a similar (but not as good) thought which was to separate out the action from the planning in code then inject the action system. So —-dry-run would pass the ConsoleOutput() action interface but without it passes a LiveExecutor() (I’m sure there’s a better name).

Assuming our system is complex enough. I guess it sits between if dry_run and execute(plan()) in its complexity.

Re: In praise of –dry-run

#145
post #31

I use --dry-run when I'm coding and I control the code. Otherwise it's not very wise to trust the application on what should be a deputy responsibility. Nowadays I'd probably use OverlayFS (or just Docker) to see what the changes would be, without ever risking the original FS.

How do you easily diff what changed between Docker and host?

The way OverlayFS works is that there's a base directory. And then there's an overlay directory that only contains the changes. Docker is based on OverlayFS.

There's two main ways overlays are used, first at build time, each line/command generates a new overlay based on the previous base, so when you do something like

FROM debian RUN apt-get update

it creates a base from the debian image , and then creates an overlay that only contains the changes introduced by apt-get update.

If you use docker inspect or docker show on the image you get a json showing exactly where the overlay directories are, you just need to navigate the overlay directory.

Second: on runtime. [Assuming you are not using volumes, (and if you use volumes, just make sure the volume starts out as empty, instead of sharing your host files)] OverlayFS is used for the runtime file changes as well, the last image is used as a base, and every files changed during runtime are added to the runtime overlay. That filesystem won't be deleted, if you only stop the docker container, the runtime files will still be present, and you can reach them by docker inspecting the running docker processes/instances, and then navigating the overlay fs as you would any directory.

You can also just use overlayfs, as far as I recall, you just use mount and unmount while specifying the OverlayFS driver and special parameters like base and overlay. Conjugating a chain of overlays is a bit more complex, but it's the same interface.

Re: In praise of –dry-run

#146
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…

I think it's configurable, but my experience with terraform is that by default when you `terraform apply` it refreshes state, which seems to be tantamount to running a new plan. i.e. its not simply executing whats in the plan, its effectively running a fresh plan and using that. The plan is more like a preview.

Re: In praise of –dry-run

#147
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)!

I was thinking that he's describing implementing an initial algebra for a functor (≈AST) and an F-Algebra for evaluation. But I guess those are different words for the same things.

Re: In praise of –dry-run

#148
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…

I think it's configurable, but my experience with terraform is that by default when you `terraform apply` it refreshes state, which seems to be tantamount to running a new plan. i.e. its not simply executing whats in the plan, its effectively running a fresh plan and using that. The plan is more like a preview.

That is the default, but the correct (and poorly documented and supported) way to use terraform is to save the plan and re-use it when you apply. See the -out parameter to terraform plan, and then never apply again without it.

Re: In praise of –dry-run

#149
If the changes your command makes are strictly to a relational database, then `--dry-run` becomes quite easy to implement: just start a transaction and never commit it. This avoids polluting the entire command with `if dryRun` checks everywhere. I've found this to be a great approach.

Re: In praise of –dry-run

#150

One of the kick-ass feature of PowerShell is you only need to add `[CmdletBinding(SupportsShouldProcess)] ` to have the `-whatIf` dry-run for your functions. Quite handy.

Powershell cmdlet macros (and the resultant parameter consistency with flags and verbs) are a great example that should make its way over to bash/zsh scripts. Given we are rewriting so many Unix utilities, it would be a great time to learn from a positive example.
Post reply on HN