Skip to content

Rewrite it in Python #789

@iFreilicht

Description

@iFreilicht

Problem

Disko is currently somewhat tricky to maintain. Part of this comes from the current architecture that puts nix itself at the center of the entire operation, and uses it as a crude templating engine for bash scripts.

This makes implementation of some features difficult. A few examples (I'll add more when I come across them):

Proposed solution

Switch to a different architecture where the nix files only define configuration values, and a bigger program written in a proper language (not bash or perl) runs nix eval --json and works with the JSON output to plan and execute all the required actions.

Considerations

Compatibility

The interface for users should not change at all. disko.devices should have the exact same type and result in the same configuration values as before.

Some programs (most notable nixos-anywhere, AFAIK) use disko's diskoScript output and call this script directly. Because this is a derivation, it should be possible to just swap them out no matter the language, as long as the resulting path has a binary with the same name. However, a simple shim with a single-line script that just calls the CLI with the required flags might be sufficient for this.

Language to use

The language should make it easy for others to contribute, have decent error-handling capabilities and be well-suited to write a CLI in.

I am therefore immediately discarding bash (or any other shell language), perl, JS, TS and Haskell.

I see three main contenders: python, rust, and go. They are all well-known and have good general support. Rust is additionally loved in the nix community for its ethos of correctness, python is super easy to write, and go is kind-of a middle-ground between the two.

One thing to consider with this choice might be closure size. As disko is often run in installers, we can expect most dependencies to not be present yet (this is the singular advantage of bash; it is guaranteed to already be present). The closure sizes of the main executable vary quite a bit:

$ nix path-info --closure-size -h nixpkgs#cargo^out
/nix/store/j6vpbh78ngj2x7jrg27pqjn2cd5mzywl-cargo-1.79.0          1.2G
$ nix path-info --closure-size -h nixpkgs#go^out                                                                                                                                                                                                                                                                                          
/nix/store/kqf4gwhq1yrchvmvqjh4adc4y9hxp9xk-go-1.22.5    248.0M
$ nix path-info --closure-size -h nixpkgs#python3^out                                                                                                                                                                                                                                                                                    
/nix/store/l014xp1qxdl6gim3zc0jv3mpxhbp346s-python3-3.12.4       166.1M

It seems somewhat unreasonable to me to require the user to download 1.2 gigabytes just to be able to run disko. A binary cache could alleviate this, though this has additional usability implications.

In the case of rust and go, there would also be compilation times added, though it's hard to say if this will matter much given the size of this project.

In general, I don't yet have a strong preference for which language to use.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions