Connecting Bundles
Welcome to part 2 of the Massdriver getting started guide! In part 1, you learned how to publish, configure, and deploy a bundle. Now you'll learn how to connect bundles together to share information between them using resources - one of Massdriver's most powerful features.
What You'll Learn
By the end of this guide, you'll understand:
✅ What resources are - How bundles share data with each other
✅ Resource types - The schema contracts that ensure type safety
✅ Publishing resource types - Making reusable data contracts available
✅ Producing resources - Updating bundles to output structured resource data
✅ Consuming resources - Using resources as inputs to other bundles
✅ Bundle connections - Connecting bundles visually in the UI
Understanding Resources and Resource Types
What Are Resources?
Resources are structured JSON outputs that bundles produce to share data with other bundles. Think of them as the "public API" of your infrastructure - they expose specific data that other bundles can consume. This is managed via two fields in the massdriver.yaml file:
- Bundles produce the resources that are specified in the
artifactsfield - Bundles consume the resources that are specified in the
connectionsfield
What Are Resource Types?
Resource types are JSON Schema specifications that define the structure and type of data that resources must contain. They create an enforceable "contract" between bundles:
- Bundles which produce resources are guaranteed to output JSON that matches the resource type schemas
- Bundles which consume resources are guaranteed to receive JSON that matches the expected resource type schema
Resource types are not paired 1-to-1 with bundles. This is intentional. Consider:
- You might have one
aws-s3-bucketresource type which contains information relevant to an S3 bucket - But multiple bundles that create different S3 buckets (logging bucket, data lake bucket, CloudFront bucket)
- All these bundles produce the same S3 resource type
This separation allows for reusable contracts across your infrastructure ecosystem. Massdriver also maintains a set of resource types which are used by our own internal bundles and public bundle templates. These resource types are available to re-use in your own bundles, or modify and republish as your own.
Step 1: Create and Publish an Resource Type
First, you'll create an resource type that contains data from the getting-started bundle in the previous guide.
Navigate to the Resource Types Directory
- In the
getting-startedrepository, you should see anartifact-definitionsdirectory - Inside, you'll find a
getting-started.jsonfile that defines the schema for your bundle's outputs
Examine the Resource Type
Open artifact-definitions/getting-started.json and examine its structure:
{
"$md": {
"name": "getting-started"
},
"required": [
"data",
"specs"
],
"properties": {
"data": {
"properties": {
"pet-name": {
"type": "string"
},
"password": {
"type": "string"
},
"shuffle": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"pet-name",
"password",
"shuffle"
],
},
"specs": {
"properties": {},
"required": [],
}
}
}
This schema defines exactly what JSON structure bundles must produce and consume. Some key points:
- The name of the resource type is in the top level
$mdblock. In this case it's namedgetting-started. - There are two top level fields:
dataandspecs. These arerequiredand have significance in Massdriver. Review the resource type docs for more information. - Within the
datablock there are separate fields each piece of data produced in thegetting-startedbundle: apet-namestring, apasswordstring, and a list of strings calledshuffle. All 3 of these fields arerequired. - The
specsfield is empty.
Publish the Resource Type
From your getting-started repository root, run:
mass definition publish -f artifact-definitions/getting-started.jsonYou should see output like:
Artifact definition <your-org>/getting-started published successfully!Make note of your organization name - you'll need it in the next steps!
Step 2: Update getting-started Bundle to Produce a Resource
Now you'll modify your getting-started bundle from the previous guide to produce a resource defined by your schema.
Update the Bundle Configuration
Navigate to your
01-deployingdirectoryOpen
massdriver.yamlFind the commented
artifacts:section (the YAML key remainsartifacts:for backwards compatibility) and uncomment it:artifacts:
required:
- your_first_artifact
properties:
your_first_artifact:
$ref: <your-organization-id>/getting-started # Replace with your org nameImportant: Replace
<your-organization-id>with your actual organization name from the previous step
Update the Resource Output
Open
src/artifacts.tf(file kept under its original name)Uncomment the
massdriver_artifactresource (the Terraform resource type retains its legacy name):resource "massdriver_artifact" "example" {
field = "your_first_artifact"
name = "A human friendly name. This is the resource for ${var.md_metadata.name_prefix}"
artifact = jsonencode({
data = {
pet-name = random_pet.name.id
password = random_password.password.result
shuffle = random_shuffle.shuffle.result
}
specs = {}
})
}
You'll notice the structure of the artifact field matches the JSON schema: a top-level data and specs field, with pet-name, password and shuffle nested under data.
Republish and Redeploy
Publish the updated bundle:
mass bundle publishIn the Massdriver UI, navigate to the project from previous guide that has
getting-starteddeployed.Notice: Your bundle now has a connection port on the right side!
Click on the
getting-startedbundle, and deploy it from the config tab so it will run the terraform and create the new resource.Explore: Click on the "Resources" tab to view and download the produced resource
Step 3: Deploy the Connecting Bundle
Now you'll deploy a second bundle that consumes a getting-started resource.
Update the Connection Reference
Navigate to your
02-connectingdirectoryOpen
massdriver.yamlScroll near the bottom of the file where the
connectionsblock is located. This is where you specify incoming required resources, known as "connections".Update the connection reference to match your organization:
connections:
required:
- your_first_connection
properties:
your_first_connection:
$ref: <your-org>/getting-started # Replace with your org name
Generate Variables from Connections
Run the bundle build command to generate variables from your connections:
mass bundle buildNotice: This updates
src/_massdriver_variables.tfto create a typed variable that matches the resource type from the connectionExamine: Look at how the resource type became a typed Terraform variable:
variable "your_first_connection" {
type = object({
data = object({
password = string
pet-name = string
shuffle = list(string)
})
specs = object({})
})
}
Publish the Connecting Bundle
Publish the connecting bundle:
mass bundle publish
Connect the Bundles in the UI
- In the Massdriver UI, drag your
connecting-bundlesbundle onto the canvas and name it - Notice: The left side has a connection port that matches your resource type
- Connect: Draw a line from the output port of your
getting-startedbundle to the input port of yourconnecting-bundlesbundle - Deploy: Click on
connecting-bundlesand click Deploy from the Config tab
Step 4: Explore the Results
Once deployed, explore what the connecting bundle created:
View the Outputs
- Click on your deployed connecting bundle
- Check the outputs in the deployment logs to see how the connected data was used:
- extended_pet_name: A new pet name using the original as a prefix
- password_based_port: A port number derived from the password length
- reshuffled_words: A new ordering of the original shuffled words
Key Takeaways
🧩 Resources enable bundle composition - Complex systems are built by connecting simple bundles
📜 Resource types ensure contracts - Type-safe data exchange between bundles
🔄 Definitions are reusable - One definition can be used by many bundles
👀 Visual connections - The UI makes infrastructure dependencies clear and manageable
🔗 Dependency enforcement - Required connections prevent incomplete deployments
What's Next?
Now that you understand bundle connections, you can:
- Create more complex architectures - Chain multiple bundles together
- Design reusable resource types - Create contracts for your infrastructure patterns
- Build custom bundles - Create your own infrastructure bundles with meaningful resources
- Explore advanced features - Learn about alarms, monitoring, and advanced bundle patterns
Congratulations! You've mastered the fundamental concepts of Massdriver's bundle system. You're ready to build real infrastructure architectures using these powerful composability patterns.