4 ms·
I don't see how you could maintain purity and reproduceability with something imperative. I used ansible for a while and it was a mess that broke half the time
by colordrops 5y ago
I don't see how you could maintain purity and reproduceability with something imperative. I used ansible for a while and it was a mess that broke half the time and was difficult to maintain.
- tracnar 5y agoDoesn't Bazel do exactly that with their Starlark language based on Python? https://bazel.build/rules/language#mutability https://bazel.build/rules/language#mutability
- pharmakom 5y agoKey aspects of Bazel are not imperative. For example the “load” functions commands must not be computed.
- tjoff 5y agoHow does that have anything to do with it being imperative and not the fundamental design of the system? How nix is architectured is exactly why it achieves purity and reproducibility, not the configuration language. It isn't even a goal of ansible in the same sense, per design. The building blocks of nix is simple, of course it can be implemented in something imperative.
- xena 5y agoThink about it like this: with Ansible you start from some unknown state of the system and then iteratively do actions to hopefully get what you want. With Nix you know what the base state of the system is, and the configuration language lets you describe your desired end state. Then the computer figures out what to do in the middle. The fundamental design of Ansible is that you do imperative steps to reach an end state. The fundamental design of NixOS is that you describe the end state and the compiler derives the intermediate steps. Yes, normally things work out with Ansible, but the devil is in the details and can involve a lot of fighting configurations that are non-cromulent.
- tjoff 5y agoYes - that was exactly my point. It has nothing to do with the configuration language. The end result of nix(os) could just as well be done from a bash script (not advisable, no). And the problems with ansible would not be any better off if they had used something like the nix-language instead.
- xena 5y agoFun fact: Nix is really a compiler from a weird Haskell like DSL to bash!
- sciurus 5y ago> The fundamental design of Ansible is that you do imperative steps to reach an end state. No, the fundamental design of configuration management systems (Ansible, Puppet, Chef, Salt, CFEngine) is that they are declarative. You say "this software should be installed, this user should exist, these files should have these contents and permissions, etc" and they figure out the right steps to take on your OS to move from the current state to your desired end state. You are right though that they can produce unexpected results since they do not describe the entire system from the ground up.
- colordrops 5y agoThat's fair, though ansible has ordered steps, so it's not entirely declarative. You are right that imperative definition is not a problem for reproduceability, but it does make things harder to reason about since you have to mentally keep track of state between steps.
- soraminazuki 5y agoI deal with Chef at work, and I wish that was even remotely true. It's not a declarative system at all because it does not have the properties of being one. Namely the part about being able to specify the end state. Chef doesn't allow you to specify the end state. Instead it allows you to specify a list of actions to be taken during deployment. The end result is affected by bunch of external inputs sent from the Chef server and every single bit of state the target server is able to observe. It is therefore impossible to reliably determine the end state of the target server before deployment. Our team has been burnt by this more than once. Other similar systems are more or less the same. They have every hallmarks of being an imperative system.
- deltaonefour 5y agoYou can. So long as the impurity is scoped to be local within a package. And the system itself only reads the output of your language to configure something. Example: def packageInstaller(pkgs: Pkg) -> Derivation: x = { req: [pkgs.a, pkgs.b] build: ... } x[req].append(pkgs.c) return buildDerivation(x) packageInstaller outputs a single package description, but you can also create something similar that easily outputs an entire configuration for the OS. You just need to keep mutation scoped within the language. The configuration that is outputted is immutable and whatever thing that's processing that configuration is not within user control. Keep in mind that mutability and immutability share a certain isomorphism. Within the nix expression language you often do something similar to mutation just as any other functional language. For example: listVersion3 = listVersion1 ++ AdditionalStuff It's just that in functional languages you're forced to keep versions of each mutation.