From 7fcd7e4b13ac20abe1aa746a4f5a3a1768cf4087 Mon Sep 17 00:00:00 2001 From: Ian Wahbe Date: Thu, 5 Feb 2026 16:20:14 +0100 Subject: [PATCH] First half --- .../index.md | 179 ++++++++++++++++++ .../meta.png | Bin 0 -> 28004 bytes 2 files changed, 179 insertions(+) create mode 100644 content/blog/recursive-package-downloading-installation/index.md create mode 100644 content/blog/recursive-package-downloading-installation/meta.png diff --git a/content/blog/recursive-package-downloading-installation/index.md b/content/blog/recursive-package-downloading-installation/index.md new file mode 100644 index 000000000000..b9afe716d547 --- /dev/null +++ b/content/blog/recursive-package-downloading-installation/index.md @@ -0,0 +1,179 @@ +--- +title: "Recursive Package Downloading & Installation" +date: 2026-02-04 +draft: false +meta_desc: "A technical deep dive into how `pulumi install` works" +meta_image: meta.png +authors: + - ian-wahbe +tags: + - features + - infrastructure-as-code +schema_type: auto + +# Optional: Social media promotional copy (for reference only, does not auto-post) +social: + twitter: + linkedin: +--- + +`pulumi install` installs everything you need to run a Pulumi project. That means [plugins](TODO: docs page for source based plugins), [local SDKs](/docs/iac/guides/building-extending/packages/local-packages/) & +language dependencies. A good mental model for `pulumi install` is that the following script works: + +```bash +$ git clone https://github.com/your-org/any-repo && cd any-repo/your-pulumi-program +$ pulumi install +$ pulumi up +``` + +Actually delivering on that promise is harder then you might think, and it's all due to [source based plugins](TODO: docs page for source based plugins). + + + +## What are source based plugins + +To understand the problem, we need to look at the anatomy of a source based plugin. A source based plugin is a +*directory* that contains a [`PulumiPlugin.yaml`](/docs/iac/guides/building-extending/components/build-a-component/#pulumipluginyaml) file: + +```go +type PluginProject struct { + Runtime ProjectRuntimeInfo `json:"runtime" yaml:"runtime"` + Packages map[string]PackageSpec `json:"packages,omitempty" yaml:"packages,omitempty"` + ... +} +``` + +*Source: [project.go:942-953](https://github.com/pulumi/pulumi/blob/f1880936441c60b3ba6faa1d4f80c922fbd6c7bc/sdk/go/common/workspace/project.go#L942-L953)* + +`Runtime` is the name of the language that the plugin is written in. `Packages` is the complicated part: `Packages` is a +map of [Pulumi Packages](/docs/iac/concepts/packages/) that need to be installed **with local SDKs** before we can run the source based +plugin. Let's walk through an example: + +Consider the following plugin directory: + +``` +./ +├── PulumiPlugin.yaml +├── index.ts +├── package.json +├── package-lock.json +└── tsconfig.json +``` + +```yaml +runtime: nodejs +packages: + my-package: https://github.com/moolumi/my-package +``` + +```typescript +import * as pulumi from "@pulumi/pulumi"; +import * as myPackage from "@moolumi/my-package"; + +interface ComponentArgs { + message: pulumi.Input; +} + +export class Component extends pulumi.ComponentResource { + result: pulumi.Output; + + constructor(name: string, args: ComponentArgs, opts: pulumi.ComponentResourceOptions) { + super("example:index:Component", name, args, opts) + + const r = new myPackage.Resource(`${name}-resource`, { + message: args.message`, + }, { parent: this }); + + this.result = r.result; + } +} +``` + +```json +{ + "name": "my-component", + "dependencies": { + "@moolumi/my-package": "file:sdks/moolumi-my-package", + "@pulumi/pulumi": "^3.218.0" + }, + "devDependencies": { + "@types/node": "^24.0.0", + "typescript": "^5.9.2" + } +} +``` + +To install `my-component`, we would need to, in order: + +1. Clone & install `https://github.com/moolumi/my-package` +1. Get the [Pulumi Schema](/docs/iac/guides/building-extending/packages/schema/) for `my-package`: `pulumi package get-schema ${install-dir(my-package)} > my-package-schema.json` +1. Generate a local SDK for `my-package`: `pulumi package gen-sdk my-package-schema.json --language typescript --out sdk/moolumi-my-package` +1. Install the locally generated SDK: `cd sdk/moolumi-my-package && npm install` +1. Install the dependencies for `my-component`: `npm install` + +{{% notes type="info" %}} +The steps for an installation include an installation. Installing components is recursive. +{{% /notes %}} + +## Installing source based plugins + +Source based plugins can reference other packages, including source based plugins. This means that every plugin +installation forms a [DAG](https://en.wikipedia.org/wiki/Directed_acyclic_graph). + +**Simple dependency chain:** + +```mermaid +graph LR + Project --> my-component + my-component --> my-package +``` + +**Complex dependency graph:** + +```mermaid +graph TD + Project --> component-a + Project --> component-b + Project --> component-c + + component-a --> component-d + component-a --> component-e + component-a --> component-f + + component-b --> component-d + component-b --> component-e + component-b --> component-f + + component-c --> component-d + component-c --> component-e + component-c --> component-f + + component-d --> resource-g + component-d --> resource-h + + component-e --> resource-g + component-e --> resource-h + + component-f --> resource-g + component-f --> resource-h +``` + +Because source based plugins declare their own dependencies, the `pulumi` CLI doesn't know what dependencies a source +based plugin has until it's already been downloaded. That leaves us with 2 ways to perform a full download: + +1. First download all source based plugins, then install them. +1. Download & install plugins at the same time. + +The first option provides a much simpler mental model: download plugins until you understand the full DAG, then perform +a (parallel) depth first traversal of the DAG to install plugins. + +The second option is more performant but also more complex: create a mutable DAG & update it as new dependency +information becomes available. This requires the ability to register create nodes in your DAG without knowing their +dependency information. + +We actually ended up implementing both options. [#20945](https://github.com/pulumi/pulumi/pull/20945) added a "download, then install" algorithm to `pulumi +install`. [#21320](https://github.com/pulumi/pulumi/pull/21320) followed up with a more general "mutable DAG" traversal. + +## Mutable DAG traversal + +... diff --git a/content/blog/recursive-package-downloading-installation/meta.png b/content/blog/recursive-package-downloading-installation/meta.png new file mode 100644 index 0000000000000000000000000000000000000000..2021885fbc2948110639e40ff0a8fd48d928cc0d GIT binary patch literal 28004 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 literal 0 HcmV?d00001