Crafting Custom Artifact Definitions
Crafting Custom Artifact Definitions
In this guide, we're going to walk through the steps to create your own custom artifact definitions in Massdriver. This is for those moments when the existing definitions just don't cut it for your unique needs. Let's demystify the process and make it as straightforward as possible. And, just in case you're looking for a primer on what artifacts and artifact definitions actually are, make sure to check out our dedicated docs for artifacts and artifact definitions.
How to Create Your Own Custom Artifact Definition
Step 1: Spotting the Need
Check out the Massdriver artifact definitions GitHub repo first. If what you need is nowhere to be found, that's your green light to craft something custom.
Step 2: Getting Started
With the Massdriver CLI, you've got the toolkit you need to forge your own definitions. It's usually easier to tweak an existing one than to start from scratch:
- Pick a Starting Point: Hunt down an existing artifact definition that's close to what you need, or use this starting template:
{
"$schema": "http://json-schema.org/draft-07/schema",
"$md": {
"name": "artifact-definition-name"
},
"type": "object",
"title": "Artifact Definition Name",
"description": "",
"additionalProperties": false,
"required": [
"data",
"specs"
],
"properties": {
"data": {
"title": "Artifact Data",
"type": "object",
"properties": {}
},
"specs": {
"title": "Artifact Specs",
"type": "object",
"properties": {}
}
}
}
- Make It Your Own: Copy its content into your favorite editor (like VS Code) and start tweaking it to suit your requirements.
Step 3: Key Components of an Artifact Definition
Every custom artifact definition should include:
- Data Block: This is where you stash the sensitive details (passwords, connection strings, you name it).
- Specs Block: Here's where the non-sensitive details go, like API versions and cloud regions.
Step 4: Tailoring Your Definition
- Refine the Data and Specs Blocks: Adapt these sections to match your specific artifact needs.
- Prune What You Don't Need: If the copied definition includes irrelevant bits (like RBAC settings you're not using), cut them out or alter them.
By the end of this step, your definition should look something like this:
{
"$schema": "http://json-schema.org/draft-07/schema",
"$md": {
"name": "artifact-definition-name"
},
"type": "object",
"title": "Artifact Definition Name",
"description": "",
"additionalProperties": false,
"required": [
"data",
"specs"
],
"properties": {
"data": {
"title": "Artifact Data",
"type": "object",
"required": [
"infrastructure",
"authentication",
"security"
],
"properties": {
"infrastructure": {
"title": "Infrastructure configuration",
"type": "object",
"required": [
"foo",
"bar"
],
"properties": {
"foo": {
"type": "string",
"title": "Foo",
"description": "Foo description",
"examples": [
],
"pattern": "^.*+$",
"message": {
"pattern": "Must be a valid format for foo."
}
},
"bar": {
"title": "Bar",
"description": "Bar description",
"additionalProperties": false,
"examples": [
],
"type": "string"
}
}
},
"authentication": {
"title": "Authentication configuration",
"type": "object",
"required": [
"foobar"
],
"properties": {
"foobar": {
"title": "Foobar",
"type": "string"
}
}
},
"security": {
"title": "Security",
"description": "Security Configuration",
"additionalProperties": false,
"required": [],
"properties": {
"iam": {
"title": "IAM",
"description": "IAM Roles And Scopes",
"additionalProperties": false,
"patternProperties": {
"^[a-z]+[a-z_]*[a-z]$": {
"type": "object",
"required": [
"role",
"scope"
],
"properties": {
"role": {
"title": "Role",
"description": "Cloud Role",
"pattern": "^[a-zA-Z ]+$",
"message": {
"pattern": "Must be a valid Cloud Role (uppercase, lowercase letters and spaces)"
},
"examples": [
"Data Reader"
]
},
"scope": {
"title": "Scope",
"description": "Cloud IAM Scope (cloud resource identifier)",
"type": "string"
}
}
}
}
}
}
}
}
},
"specs": {
"title": "Artifact Specs",
"type": "object",
"properties": {
"cloud": {
"properties": {
"region": {
"type": "string",
"title": "Cloud Region",
"description": "Select the cloud region you'd like to provision your resources in."
}
}
}
}
}
}
}
Step 5: Publishing to Massdriver
Got your definition looking sharp? Use the mass definition publish -f /path/to/definition.json
command in the CLI to send it out into the world.
Step 6: Fetching Your Masterpiece
Once published, snag your artifact definition with the mass definition get org/definition-name
command to confirm it's ready for action in your bundles.
Step 7: Using Your Custom Artifact Definition
Now that your custom artifact definition is published, you can use it in your bundles. Just reference it in your bundle's artifacts
field and structure your _artifacts.tf
file, and you're good to go.
artifacts:
required:
- artifact_definition_name
properties:
artifact_definition_name:
$ref: acme/artifact-definition-name
resource "massdriver_artifact" "artifact_definition_name" {
field = "artifact_definition_name"
provider_resource_id = artifact_dummy_resource.main.id
name = "Artifact Dummy Resource ${var.md_metadata.name_prefix}"
artifact = jsonencode(
{
data = {
infrastructure = {
foo = artifact_dummy_resource.main.foo
bar = artifact_dummy_resource.main.bar
}
authentication = {
foobar = artifact_dummy_resource.main.foobar
}
security = {
iam = {
"read" = {
role = "Data Reader"
scope = artifact_dummy_resource.main.id
}
}
}
}
specs = {
cloud = {
region = artifact_dummy_resource.main.region
}
}
}
)
}
To confirm that your custom artifact definition is working as expected for your bundle, run the mass bundle lint
and mass bundle build
commands to check for any issues. When you're ready to publish your bundle changes, mass bundle publish
will publish your bundle to your Bundle Catalog.
Customizing Massdriver
Customizing Onboarding
Massdriver lets you fully customize the onboarding experience for cloud credentials and other artifact types. You can define onboarding instructions, UI labels, and icons directly in your artifact definition using the $md
and $md.ui
fields. This enables you to provide clear, step-by-step guidance for your users when they add new credentials.
For example, the onboarding screen for cloud credentials (see below) is driven by the ui.instructions
array in your artifact definition. Each instruction can include a label and content, allowing you to walk users through complex setup steps with clarity.
Relevant schema fields:
$md.label
: Sets the display name for your artifact in the UI.$md.icon
: Sets a custom icon for your artifact.$md.ui.instructions
: An array of onboarding steps, each with alabel
andcontent
, shown to users during credential setup.
See a real-world example of onboarding instructions in the aws-iam-role artifact definition.
Note on Icons and Instructions
Currently, icons (as data URLs) and instructions.content
(as base64-encoded markdown) are packed directly into the JSON Schema. With our upcoming move to OCI for artifact definitions (as we've already done for bundles), you'll soon be able to include these files directly in the same directory as your definition—no more packing required. Stay tuned for updates! Here is the script we use for packaging artifact definitions.
Customizing the Artifact Types that can be defaulted in an Environment
Massdriver environments support "environment default" artifacts—resources like credentials, networks, or DNS zones that are commonly shared across multiple bundles. You can control which artifact types are eligible to be set as environment defaults by specifying the ui.environmentDefaultGroup
field in your artifact definition.
When you set this field, your artifact type will appear in the environment overlay, allowing users to assign a default resource for that group (e.g., default network, default credentials) without having to connect it individually to every bundle. This streamlines environment setup and reduces visual clutter in complex diagrams.
Relevant schema fields:
$md.ui.environmentDefaultGroup
: Adds your artifact type to the "environment default" overlay under the specified group (e.g.,networking
,authentication
,dns
). This is what makes an artifact eligible to be set as a default in an environment.
Note: There is a special 'magic' environment default group called
credentials
. Assigning your artifact to this group will make it appear on the credentials page and enables Massdriver to fetch credentials for use in your workflows. Besides that you can use anyenvironmentDefaultGroup
name that makes sense for your team.
See a real-world example of adding an environment default in the aws-vpc artifact definition.
$md.ui.connectionOrientation
: Controls how the artifact appears on the canvas. If set to"link"
, users can draw lines to connect bundles to the artifact. If set to"environmentDefault"
, the artifact is only shown as a default and not as a connectable box. These options are independently controllable, so you can allow both defaulting and explicit connections if desired. For example, SREs might want to draw lines to a shared Kubernetes cluster, while end developers only see it as a default and don't interact with it directly.
Example snippet:
{
"$md": {
"name": "aws-iam-role",
"label": "My Cloud Credential",
"icon": "https://example.com/my-icon.svg",
"ui": {
"environmentDefaultGroup": "authentication",
"connectionOrientation": "environmentDefault",
"instructions": [
{
"label": "Step 1: Create a Service Account",
"content": "Go to your cloud provider and create a new service account..."
}
]
}
}
}
References:
By leveraging these schema fields, you can tailor both the onboarding experience and environment default behavior for your custom artifact types, ensuring a seamless and intuitive experience for your users.
Wrapping Up
And there you have it! Creating your own artifact definitions in Massdriver opens up a world of customization for your cloud infrastructure projects. By following these steps, you're well on your way to tailoring Massdriver to your project's unique requirements. If you've got any questions or need a hand, don't hesitate to reach out to our team. We're here to help you make the most of Massdriver's powerful features. Happy crafting!