4 ms·
This seems extremely dismissive and shallow. The imperative part of that code appears to be analogous to templating. The actual work done under the covers is n
by jjnoakes 3y ago
This seems extremely dismissive and shallow.
The imperative part of that code appears to be analogous to templating. The actual work done under the covers is not imperative, but is based on the difference between the result of the template execution and the current state of the system. That's what makes it declarative.
- verdverm 3y agoIt really depends on the interaction between the user's Pulumi script and the Pulumi engine. If there is more than one back and forth, you become declarative, even if you imperatively generate a "declarative" intermediate representation (not really sure what state file at a point in time could ever be imperative), you then would get back some data from the engine, then make choices about what to send off to the engine in the next request. It's important to understand that with Pulumi, you can end up in either situation. You have to be careful to not become imperative overall is probably the better way to consider this. https://www.pulumi.com/docs/languages-sdks/javascript/#entrypoint https://www.pulumi.com/docs/languages-sdks/javascript/#entry... Another way this can break down is if the user writes code to call the same APIs in the middle of a Pulumi script. I meant to try this myself to verify it works, but I would assume that Pulumi is not stopping me from doing something like this.
- jjnoakes 3y agoIn general maybe, but in the specific context above, I think calling that loop declarative is accurate, and laughing at that classification is a poor response rooted in a deep misunderstanding.
- verdverm 3y agoI was just wondering what stops me from reading and writing to a cloud bucket like an infinite tape? https://www.pulumi.com/registry/packages/gcp/api-docs/storage/getbucketobjectcontent/ https://www.pulumi.com/registry/packages/gcp/api-docs/storag...
- verdverm 3y agoimport pulumi from pulumi_gcp import storage bucket = "hof-io--develop-internal" name = "pulumi/hack/condition.txt" cond = False msg = "running" cnt = 0 while not cond: cnt += 1 key = storage.get_bucket_object_content(name=name, bucket=bucket) print(cnt, key.content) if key.content == "exit": msg = "hallo!" break pulumi.export('msg', msg) pulumi.export('cnt', cnt) --- 769 exit 770 exit 771 exit 772 exit 773 exit 774 exit 775 exit Outputs: cnt: 775 msg: "hallo!" Resources: + 1 to create info: There are no resources in your stack (other than the stack resource). Do you want to perform this update? [Use arrows to move, type to filter] yes > no details ---- Of note, all but the last exit had a newline, until I `echo -n` the file I copied up --- ooo... 348 what?!?! 349 what?!?! 350 what?!?! 351 what?!?! 352 what?!?! 353 what?!?! 354 what?!?! 355 what?!?! 356 what?!?! 357 what?!?! 358 what?!?! 359 exit Outputs: cnt: 359 msg: "hallo!" Resources: + 1 created Duration: 27s --- I uploaded a different file while waiting to be asked to continue, and then proceeded to get different outputs Note, while I can get the contents of a bucket in TF, I cannot build a loop around it as I have above https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/s3_object https://registry.terraform.io/providers/hashicorp/aws/latest... TF might be susceptible to the same file contents manipulation between plan & apply as well, but then again, you can save a plan to a file and then run it later, so maybe not? Another experiment seems to be in order
- AaronFriel 3y agoI think this is an advantage of Pulumi, here are two use cases: 1. Creating a resource where created is not the same as ready. This is extraordinarily common with compute resources (a virtual machine, a container, an HTTP server, a process) where attempting to create follow-up resources can result in costly retry-back-off loops. Even when creating Kubernetes resources, Pulumi will stand up an internet-connected deployment more quickly than many other tools because you can ensure the image is published before a pod references it, the pod is up before a service references it, and so on. (The Kubernetes provider bakes some of these awaits in by default.) 2. Resources graphs that are dynamic, reflecting external data sources at the moment of creation. Whether you want to write a Kubernetes operator, synchronize an LDAP directory to a SaaS product, or one of my favorite examples. When I set up demos, I often configure the authorized public IPs dynamically: import * as publicIp from 'public-ip'; new someProvider.Kubernetes.Cluster('cluster', { apiServerAccessProfile: { authorizedIPRanges: [await publicIp.v4()], enablePrivateCluster: false, }, }
- lmm 3y ago> This seems extremely dismissive and shallow. When someone tries to make a sophisticated argument that up is down and white is black, dismissive and shallow is the right response. > The actual work done under the covers is not imperative Having a declarative layer somewhere in the stack doesn't make something declarative, if that's not the layer you actually use to work on and reason about the system. See the famous "the C language is purely functional" post.
- Pet_Ant 3y agoI’m guessing this is the reference? http://conal.net/blog/posts/the-c-language-is-purely-functional http://conal.net/blog/posts/the-c-language-is-purely-functio...
- jjnoakes 3y ago> When someone tries to make a sophisticated argument that up is down and white is black This is where the deep misunderstanding is coming from.