5 ms·
> But when you've copy/pasted tens of thousands of lines of YAML around all over your codebase to manage hundreds or thousands of resources, the value of abstra
by mixedCase 7y ago
> But when you've copy/pasted tens of thousands of lines of YAML around all over your codebase to manage hundreds or thousands of resources, the value of abstraction, reuse, well defined interfaces, and tooling to manage that complexity feels to me essential to the scale of the problem.
You're lumping in HCL (and languages like Dhall by extension) with static serialization formats and criticizing them for a characteristic only found in the latter.
HCL is programmable and has a fair model for code reusability through modules, state outputs, for-expressions and other kinds of expressions.
Add in a proper language with types like Dhall and you have a configuration language where you can apply all the transformations you could want with a much higher safety and robustness floor than a turing-complete language that allows you to make all sorts of messes.
It's specially dangerous to have a turing-complete language for configuration once you factor in that the reflex of an inexperienced developer who is more likely to make these messes is to use a tool they're already familiar with even when the tool is actively harmful to their goals, as Pulumi facilitates.
- throwaway894345 7y ago> It's specially dangerous to have a turing-complete language for configuration once you factor in that the reflex of an inexperienced developer who is more likely to make these messes is to use a tool they're already familiar with even when the tool is actively harmful to their goals, as Pulumi facilitates. "Turing complete" is a red herring. You can write a program in Dhall that will continue to run long after we're all dead. But this doesn't happen in practice and/or when it does we notice something is wrong fairly quickly and correct the problem. And because these infra-as-code-and-not-configuration solutions generate configuration, if you do have a loop that doesn't terminate or similar, it's not a problem because your program never deploys any changes. As for making messes, our experienced developers make more of a mess with static configuration because it's fundamentally impossible to manage large static configurations with their inherent repeatable segments that must be kept in sync. The static configuration players try to solve for this by introducing hacky mechanisms for reuse (macros and nested-stacks in CloudFormation, text templates via Helm for Kubernetes, etc), but these fall over very quickly as hacks do.
- mixedCase 7y ago> "Turing complete" is a red herring. You can write a program in Dhall that will continue to run long after we're all dead. It's not the avoidance of the halting problem the reason these languages are better for the task. It's the benefit of having limitations that come with being turing incomplete that prevent us from doing a lot of stupid stuff without realizing it and doing "hacky workarounds" without properly understanding the problem we face. > As for making messes, our experienced developers make more of a mess with static configuration because it's fundamentally impossible to manage large static configurations with their inherent repeatable segments that must be kept in sync. Or don't do static configuration and just use something like Terraform where you can just reference a resource and pass it around.
- throwaway894345 7y ago> It's the benefit of having limitations that come with being turing incomplete that prevent us from doing a lot of stupid stuff without realizing it and doing "hacky workarounds" without properly understanding the problem we face. You'll have to articulate your said benefits to be sure, but I would wager that the principle reason to be turing incomplete is to address the halting problem and that the benefits you're thinking about come from other properties of the language (functional purity, immutability, limitations on I/O, type safety where applicable, etc). Notably, there are lots of hacky workarounds employed in HCL and YAML because people don't understand the problem properly. The problem requires that we can generate arbitrary static configuration from a fixed set of inputs. If your organization is so inept that they keep adding in infinite loops and/or I/O, then by all means, try something like Dhall or Starlark (unfamiliar vs not-type-safe, pick your poison); however, if this is a consistent problem in your organization you probably need to replace your humans because these programs aren't hard to write correctly. > Or don't do static configuration and just use something like Terraform where you can just reference a resource and pass it around. Because this only addresses reuse at the resource level. You can do the same thing in CloudFormation; it's not adequate. For example, not everything is a resource. You ultimately need the ability to generate arbitrary static configuration. Terraform probably has lots of other disparate features that collectively address a good portion of the solution space, but programming languages have a unified concept ("functions") that satisfy the whole solution space and programmers are already familiar with them. Terraform's job should be taking static configs and applying them to infrastructure--let a real programming language generate those configs, or at least offer dynamic configuration language that is designed with a proper understanding of the problem (to use your words).
- joeduffy 7y ago[Disclaimer: also member of the Pulumi team.] We've worked with a lot of end users to migrate from Terraform, and we honestly do see a lot of copy-and-paste. I agree that it's not as rampant as with YAML/JSON, however, in practice we find a lot of folks struggle to share and reuse their Terraform configs for a variety of reasons. Even though HCL2 introduced some basic "programming" constructs, it's a far cry from the expressiveness of a language like Python. We frequently see not only better reuse but significant reduction in lines of code when migrating. Being able to create a function or class to capture a frequent pattern, easily loop over some data structure (e.g., for every AZ in this region, create a subnet), or even conditionals for specialization (e.g., maybe your production environment is slightly different than development, us-east-1 is different, etc). And linters, test tools, IDEs, etc just work. For comparison, this Amazon VPC example may be worth checking out: - Terraform: https://github.com/terraform-aws-modules/terraform-aws-vpc/blob/master/main.tf https://github.com/terraform-aws-modules/terraform-aws-vpc/b... - Pulumi (Python): https://github.com/joeduffy/pulumi-architectures/blob/master/aws-py-base-infra/__main__.py https://github.com/joeduffy/pulumi-architectures/blob/master... - CloudFormation: https://github.com/aws-quickstart/quickstart-aws-vpc/blob/master/templates/aws-vpc.template https://github.com/aws-quickstart/quickstart-aws-vpc/blob/ma... It's common to see a 10x reduction in LOCs going from CloudFormation to Terraform and a 10x reduction further going from Terraform to Pulumi. A key importance in how Pulumi works is that everything centers around the declarative goal state. You are shown previews of this (graphically in the CLI, you can serialize that as a plan, you always have full diffs of what the tool is doing and has done. This helps to avoid some of the "danger" of having a turing-complete language. Plus, I prefer having a familiar language with familiar control constructs, rather than learning a proprietary language that the industry generally isn't supporting or aware of (schools teach Python -- they don't teach HCL). In any case, we appreciate the feedback and discussion -- all great and valid points to be thinking about -- HTH.
- mtalantikite 7y ago"For comparison, this Amazon VPC example may be worth checking out" It might be better to compare how to use the module/stack: - Terraform: https://github.com/terraform-aws-modules/terraform-aws-vpc https://github.com/terraform-aws-modules/terraform-aws-vpc - Pulumi: https://github.com/joeduffy/pulumi-architectures/tree/master/aws-py-base-infra https://github.com/joeduffy/pulumi-architectures/tree/master... So as a user, can I configure this Pulumi VPC stack before it's instantiated? Or do I have to use the defaults first and then use the CLI to change things? Do these CLI changes then get placed into code, or just into state? Does that mean I'm now in a situation where the code doesn't match the state? Personally I find the Terraform configuration much easier to reason about, I see exactly where resources are declared just by scanning the file. (But I've also used Terraform a lot). Edit: Ah, maybe I have to configure it via this config.py file [1]? I appreciate what Pulumi is trying to accomplish, but that is certainly not a config format I'd like to be using. Maybe you could use HCL or YAML for it? ;) Edit 2: Another last thought, I think a lot of the mindset in Terraform comes from Go, where the proverb "A little copying is better than a little dependency" is pretty well adopted. Before I started writing Go as my main language I didn't appreciate that mindset, but after 5 years with Go I've found it more and more appropriate [2]. [1] https://github.com/joeduffy/pulumi-architectures/blob/master/aws-py-base-infra/config.py https://github.com/joeduffy/pulumi-architectures/blob/master... [2] https://go-proverbs.github.io/ https://go-proverbs.github.io/ -- https://www.youtube.com/watch?v=PAAkCSZUG1c&t=9m28s https://www.youtube.com/watch?v=PAAkCSZUG1c&t=9m28s