Lesson 7March 20, 20266 min read

Components Deep Dive: Generic Components in Bunnyshell

Generic components are the Swiss Army knife of Bunnyshell's component system. While Docker Compose and Helm handle containerized workloads, Generic components let you run anything — from Terraform to shell scripts to API calls — as a managed part of your environment's lifecycle. Watch the video above for practical examples, then read on to understand how to use this powerful tool effectively.

What Are Generic Components?

A Generic component in Bunnyshell is fundamentally different from the other two component types. It does not deploy a container or install a Helm chart. Instead, it executes scripts that you define, running them in a controlled context with access to environment variables, secrets, and outputs from other components.

Every Generic component has two lifecycle hooks: deploy and destroy. The deploy script runs when the environment is created or redeployed. The destroy script runs when the environment is deleted. This symmetry is important — it ensures that any resources your deploy script provisions are properly cleaned up when the environment is torn down.

For example, a deploy script might use Terraform to create an Amazon RDS database instance, and the destroy script would run terraform destroy to delete that instance. Without the destroy hook, you would accumulate orphaned cloud resources every time an ephemeral environment was cleaned up — a fast path to an ugly cloud bill.

Generic components are declared in your bunnyshell.yaml alongside your other components, and they participate in the same dependency graph. This means you can configure a Generic component to run before your application services start, ensuring that the external resources it provisions are ready when your containers need them.

Use Cases: Terraform, Scripts, and External Services

The versatility of Generic components means they show up in a wide variety of architectures. Here are the most common patterns.

Terraform provisioning is the flagship use case. Many production applications depend on managed cloud services — RDS databases, ElastiCache clusters, S3 buckets, SQS queues — that are provisioned through Terraform rather than deployed as containers. With a Generic component, you can run terraform apply during environment creation to provision these resources, and terraform destroy during environment deletion to clean them up. The Terraform state can be stored in a remote backend, and the outputs (like a database connection string) can be passed to other components as environment variables.

Database seeding and migrations are another common use case. After your database container or managed instance is running, you might need to run schema migrations and load test data. A Generic component with a deploy script that runs rails db:migrate && rails db:seed (or the equivalent for your framework) ensures every environment starts with a consistent, usable dataset.

Third-party service configuration covers cases where your application depends on external SaaS products. If your app uses Auth0 for authentication, you might need to create a test tenant and configure redirect URLs that match the ephemeral environment's auto-generated URLs. A Generic component can make the necessary API calls to Auth0 during deploy and clean up the tenant during destroy.

Custom infrastructure setup handles anything else that does not fit neatly into a container. DNS record creation, TLS certificate provisioning, VPN tunnel configuration, or firewall rule updates can all be managed through Generic component scripts.

Configuring Deploy and Destroy Scripts

The practical configuration of a Generic component in bunnyshell.yaml involves specifying the runner image (the container where your scripts execute), the deploy command, and the destroy command.

The runner image is a container that has the tools your scripts need. If you are running Terraform, you would use a Terraform Docker image. If you are making API calls, a lightweight image with curl or a language runtime might suffice. You can use any public or private container image as the runner.

Your deploy and destroy scripts have access to all environment variables defined in the Bunnyshell configuration, including secrets. They also have access to interpolated values from other components. This means your Terraform script can receive the Kubernetes namespace, the environment name, and the URLs of other services as input variables — making your infrastructure code fully dynamic and environment-aware.

One important consideration is idempotency. Because redeploys trigger the deploy script again, your scripts should be safe to run multiple times. Terraform handles this naturally (it computes a diff and only applies changes), but custom shell scripts need to be written with idempotency in mind. Check if a resource exists before creating it. Use upsert operations instead of insert. Guard your scripts against partial failures from previous runs.

Practical Tips for Generic Components

Keep your deploy scripts focused. If you find a Generic component doing too many unrelated things, split it into multiple Generic components with explicit dependencies between them. This makes failures easier to diagnose and gives you more granular control over the deployment order.

Always implement the destroy hook. It is tempting to skip it when you are iterating quickly, but orphaned cloud resources from ephemeral environments add up fast. The discipline of writing a destroy script for every deploy script will save your team money and keep your cloud accounts clean.

Test your scripts locally before integrating them into Bunnyshell. If your deploy script runs Terraform, make sure terraform plan produces the expected output in isolation. If it makes API calls, verify them with curl or a test script. Generic components give you maximum flexibility, but that also means there is no guardrail beyond your own testing.

With Docker Compose, Helm, and Generic components in your toolkit, you have everything you need to model any application architecture in Bunnyshell. The rest is just configuration — and practice.

Ship faster starting today.

14-day full-feature trial. No credit card required. Pay-as-you-go from $0.007/min per environment.

Frequently Asked Questions

What is a Generic component in Bunnyshell?

A Generic component lets you run arbitrary scripts during the deploy and destroy phases of an environment lifecycle. Unlike Docker Compose or Helm components that deploy containers, Generic components execute custom commands — making them ideal for provisioning cloud resources with Terraform, configuring external services, seeding databases, or any task that requires custom tooling.

What are common use cases for Generic components?

The most common use cases include provisioning cloud-managed databases or storage with Terraform, configuring third-party services like Auth0 or Stripe test environments, running data migration or seed scripts, and setting up DNS records or TLS certificates for custom domains. Essentially, anything that is not a containerized service but needs to exist for your environment to function.

How do Generic component lifecycle hooks work?

Generic components have two primary hooks: deploy and destroy. The deploy hook runs when the environment is created or redeployed, and the destroy hook runs when the environment is deleted. Each hook executes a script you define, and the scripts have access to environment variables including outputs from other components — enabling you to chain dependencies across your environment.