7 ms·
[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
by joeduffy 6y 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 6y 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
- joeduffy 6y agoYou're right, the Pulumi example is a project, not a reusable module. There are a few approaches to making it modular: 1) The project does support config. So if you want to change (e.g.) the number of AZs, you can say $ pulumi config set numberOfAvailabilityZones 3 $ pulumi up And Pulumi will compare the current infrastructure with the new goal state, show you the diff, and then let you deploy the minimal set of changes to bring the actual state in line with the new goal state. This works very much like Terraform, CloudFormation, Kubernetes, etc. 2) You can make this into a library using standard language techniques like classes, functions, and packages. These can use a combination of configuration as well as parameterization. If you wrote it in Python, you can publish it on PyPI, or JavaScript on NPM, or Go on GitHub -- or something like JFrog Artifactory for any of them. This makes it easy to share it with the community or within your team. 3) We offer some libraries of our own, like this one: https://github.com/pulumi/pulumi-awsx/tree/master/nodejs/awsx/ec2 https://github.com/pulumi/pulumi-awsx/tree/master/nodejs/aws.... That includes an abstraction that's a lot like the Terraform module you've shown, and cuts down even further on LOC to spin up a properly configured VPC. I am a big Go fan too, so I very much know what you're saying. (In fact, we implemented Pulumi in Go.) Even with Go, though, you've got funcs, structs, loops, and solid basics. Simply having those goes a long way -- as well as great supporting tools -- and you definitely do not need to go overboard with abstraction to get a ton of benefit right out of the gate. Again, I'm biased and YMMV :-)
- mtalantikite 6y ago"The project does support config. So if you want to change (e.g.) the number of AZs, you can say..." Cool, is it possible to do that without having to use the CLI? Are you doing any sort of state locking here? I've seen ops teams get saved from potentially horrible situations by Terraform's dynamodb state locking. "You can make this into a library using standard language techniques like classes, functions, and packages." That's pretty nice and it seems like it'll get you the same functionality as a Terraform module. Do you have any plans of releasing something like the Terraform Registry to help with discoverability? Also, do you have any docs on writing providers? I've had to do that a few times for Terraform and getting up and running with that was pretty easy as a Go developer. I wouldn't really want to do that for every supported language though (no offense C#). I'm seeing that some of this is using codegen to read the equivalent Terraform provider and generate the Pulumi provider from that schema. Is that the preferred workflow here for providers that already exist in the Terraform ecosystem?
- pm90 6y ago> 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. I don't see this as such a terrible problem. The configurations may have more LOC's but there are not as many surprises. The dependency of declarable configuration makes it rock solid and favorable among operations teams who need to make these kinds of changes all the time. > 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). I understand the reason to want this. Having worked closely with developers, lack of familiarity with HCL makes it much less accessible. However, from an operations perspective, I am GLAD that HCL is a very limited language. No imports of libraries all over the place (in your infrastructure configurations, no less!).
- throwaway894345 6y ago> I don't see this as such a terrible problem. The configurations may have more LOC's but there are not as many surprises. The dependency of declarable configuration makes it rock solid and favorable among operations teams who need to make these kinds of changes all the time. The issue is that your static configs often have lots of boilerplate sections that have to be kept in sync. Further, you can use an imperative language like Python, JS, etc and still write in a completely declarative fashion (or you can use a functional language which tend to be declarative out of the box). Conversely, you can model an AST in YAML (which is what CloudFormation is trending toward) and get the worst of all worlds. Bottom line: don't conflate "reusability" with "imperative" or "static" with "declarative".
- pm90 6y ago> The issue is that your static configs often have lots of boilerplate sections that have to be kept in sync. Yes, I agree with this. However, its predictable. As an operations person, I value predictability and am willing to pay the price of keeping static configs in sync. > Further, you can use an imperative language like Python, JS, etc and still write in a completely declarative fashion (or you can use a functional language which tend to be declarative out of the box). Conversely, you can model an AST in YAML (which is what CloudFormation is trending toward) and get the worst of all worlds. Bottom line: don't conflate "reusability" with "imperative" or "static" with "declarative". Hold on, I'm not conflating anything. Saying that "you can write terrible things in any language" isn't anything new. We choose to use languages that provide certain guarantees that we need for the domain that we're working in. For infrastructure, declarative languages are a lot more suitable for the properties they provide (i.e. no surprises, limited functionality etc.). Its "possible" to use static types in Python, how many do that?
- mixedCase 6y agoLooking at your Terraform and Python scripts I see two different scripts doing different things with different abstraction levels and different configuration toggles. It's ironic that you sell as a plus that Python allows you to easily loop over data structures and make resources codnitional, because pretty much all your Terraform resources there are conditional (with a few looping over lists for DRY purposes), while few of the Python resources are. Many of the lines saved for declaring identical resource types are just because either the Terraform resource is declared with unnecessary values or because the Python one has a default value, which can be provided as well in Terraform. But yeah, the bulk of the difference is that the scripts are doing different things by declaring different sets of resources. > 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). Which comes back to my point about inexperienced (or the "10x" ones that cut corners until the table is round and then leave) developers preferring familiarity over using a specialized tool that takes into account common pain points, further fragmenting the space through "worse is better". I am certain I will die employed on cleaning up ORM messes left by developers that didn't want to learn SQL despite having a whole field of mathematics backing it; so if you're successful, odds are I will also end up fixing some day the "declarative output" a Pulumi script produced in a developers computer that is not reproducible anywhere else because it makes a request to his home server and mutates an array of resources somewhere depending on that response, the current time, the system locale and the latest tweet by Donald Trump.
- mtalantikite 6y ago"Many of the lines saved for declaring identical resource types..." Yeah, it seems a bit silly to say that a benefit is saved lines of code, yet the Terraform example is setup to do quite a lot more than the Pulumi example. The resources are just there and turned off with the "count" configuration. The Pulumi example isn't doing any of the RDS, Redshift, Elasticache, Database ACL, VPN gateway, etc things. This example is a pretty substantial module and I'd guess the LOC would be pretty similar between the two if the functionality were closer.
- rad_gruchalski 6y ago> 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. I would risk to say that it’s not the Terraform that makes the people to copy / paste. It’s the people. Call it lack of knowledge, not enough time, laziness, tight schedules... Once your customers are on their own, new people join - no knowledge of Pulumi, resources get added / moved / evolve, there will be copy / paste in their Pulumi code too. Not defending Terraform here. Just adding a point to the discussion.
- twunde 6y agoSome of this is truly on terraform. The for construct (and looping in general) was only added in TF 12, released in May 2019. Older codebases didn't have a real way to support looping so there's more copy paste there. TF supports ternary conditionals, but not true if statements, which makes adding more complicated if logic difficult. The reality is that all programming languages have significant copy paste codebases using them, but there are features which help reduce the amount of it. Terraform is missing some of those features, and many of the features it does have were introduced in tf 12, which is less than a year old.
- rad_gruchalski 6y agoYes. But Terraform (hcl) is not a programming language. It’s interesting that some people bring up sbt as an example of how to use a „programming language” for configuration. The reason why sbt became dominant was the weight of Lightbend (Typesafe). There was no way to get away from it. Frankly, sbt can be awful mashup of copy / paste too. sbt is so much magic, I would not be surprised to discover that majority the folks who use sbt, have no actual clue why stuff works the way it works. I haven’t tried Pulumi yet, I will try when I get the chance. I am eagerly waiting for an opportunity to use it. Hopefully it will surprise me in a positive way. Surely, it can deliver on what it promises. I have very fond memories of Chef and cookbooks in Ruby, it can be done. Edit: personally, Chef solo (with right tooling to eliminate the server), was the best experience so far. If Pulumi can improve on that (no agent), I’m looking forward to take it for a test drive.
- Dunedan 6y ago> It's common to see a 10x reduction in LOCs going from CloudFormation to Terraform […] Excuse me, but that's bullshit. Show me a single example where that's the case for AWS resources both supported by CloudFormation and Terraform. I'm pretty sure there is none. Not even your quoted example shows such a difference. And that example isn't even an apples to apples comparison, as the CloudFormation template contains much more logic, like the parameter definitions, which are spread into separate files in the Terraform example. You also quote, and I have to assume that's intentional, the JSON representation of the CloudFormation template, while the YAML representation in the same repository shows that writing the template as YAML file already cuts the LOC in half.
- di4na 6y agoI would point out that Dhall solves these problems with one simple fundamental construct: the function. And still keep it terminating. You can do it but it means doing more cognitive engineering than "just throw python at it". Another point: you can have a declarative turing complete language. I would really like to see people bring prolog like languages to things like pulumi and terraform. That would also allow to get convergent concurrent application which means we could get proper collaboration. That would be a strong move ahead for devops.