Skip to main content
Version: v2

Getting Started

This guide will walk through creating a new extension from scratch.

Prerequisites

Note: Extensions development is only currently supported on Mac and Linux. Windows is not currently supported.

You will need nodejs v16 installed (Tested with node version: v16.19.1).

You'll also need the yarn package manager installed, which can be done with npm install -g yarn.

Creating the Application

To develop a new extension, you need an application UI to host it during development. Rancher provides a helper to create a skeleton application for you. This gives you a full version of the Rancher UI that can be used to develop and test your extension.

Rancher now publishes a single npm package, @rancher/extension, to help bootstrap the creation of the application and extension. This replaces the previous separate creators (@rancher/app and @rancher/pkg).


Building Extensions for Different Rancher Versions

When creating extensions, it is important to match the version of the @rancher/extension package with the target Rancher version:

  • For Rancher v2.7 and v2.8: Use the legacy-v1 tag.
  • For Rancher v2.9: Use the legacy-v2 tag.
  • For Rancher v2.10 or later: Use the latest version of @rancher/extension. Follow the latest documentation for this version

Creating an Extension

Create a new folder and run:

npm init @rancher/extension@legacy-v2 my-app [OPTIONS]
cd my-app

This command will create a new folder my-app and populate it with the minimum files needed.

Note: The skeleton application references the Rancher dashboard code via the @rancher/shell npm module.

Extension Options

There are a few options available to be passed as an argument to the @rancher/extension script:

OptionDescription
--update | -uThis will update all dependencies within the extension to match the declared version of the @rancher/shell library based on the tag. See the Updating Guide for usage.
--app-name | -a <name>Allows specifying a different name for the skeleton application instead of using the extension name.
--skeleton-only | -sInstalls only the skeleton application without creating the extension package.
-lThis will automatically add the .gitlab-ci.yml pipeline file for integration with GitLab
-wDoes not add the Github workflow files build-extension-catalog.yml, build-extension-charts.yml to be used as Github actions. These files will be added automatically by default.
-tDoes not add the template folders automatically into the Extension package. These folders will be added automatically by default

Installing Rancher

See https://ranchermanager.docs.rancher.com/getting-started/installation-and-upgrade. Note: Not all Linux distros and versions are supported. To make sure your OS is compatible with Rancher, see the support maintenance terms for the specific Rancher version that you are using: https://www.suse.com/suse-rancher/support-matrix/all-supported-versions

The above linked installation docs cover two methods confirmed to work with the Dashboard:

To use the most recent and compatible version of Rancher that is actively in development, use the version tag v2.9-head when installing Rancher. For example, the Docker installation command would look like this:

sudo docker run -d --restart=unless-stopped -p 80:80 -p 443:443 --privileged -e CATTLE_BOOTSTRAP_PASSWORD=OPTIONAL_PASSWORD_HERE rancher/rancher:v2.9-head

Dashboard provides convenience methods to start and stop Rancher in a single docker container

yarn run docker:local:start
yarn run docker:local:stop // default user password as "password"

Note that for Rancher to provision and manage downstream clusters, the Rancher server URL must be accessible from the Internet. If you’re running Rancher in Docker Desktop, the Rancher server URL is https://localhost. To make Rancher accessible to downstream clusters for development, you can:

  • Use ngrok to test provisioning with a local rancher server
  • Install Rancher on a virtual machine in Digital Ocean or Amazon EC2
  • Change the Rancher server URL using <dashboard url>c/local/settings/management.cattle.io.setting

Also for consideration:

  • K3d lets you immediately install a Kubernetes cluster in a Docker container and interact with it with kubectl for development and testing purposes.

You should be able to reach the older Ember UI by navigating to the Rancher API url. This same API Url will be used later when starting up the Dashboard.

Running the Development Environment

You can run the app with:

yarn install
API=<Rancher Backend URL> yarn dev

You should be able to open a browser at https://127.0.0.1:8005 and you'll get the Rancher Dashboard UI. Your skeleton application is a full Rancher UI - but referenced via npm.

Creating an Extension as a top-level-product

The next step is to create an extension. As a Getting Started example, we'll demonstrate an extension for a Top-level product, but you also have the option to create an extension for a Cluster-level product.

Creating an Extension Package

Rancher provides a helper to add an extension, allowing you to manage multiple extensions or a single extension within the parent folder.

To create a new extension, the command and configuration depend on the Rancher version you are targeting:

  • For Rancher v2.7 and v2.8, use the legacy-v1 tag.
  • For Rancher v2.9, use the legacy-v2 tag.

Examples by Rancher Version

  1. For Rancher v2.7 and v2.8:
npm init @rancher/extension@legacy-v1 my-app [OPTIONS]
  1. For Rancher v2.9:
npm init @rancher/extension@legacy-v2 my-app [OPTIONS]

Refer to the prerequisites section at the beginning of this document for the appropriate Node.js version to use based on the Rancher version you are targeting.

Matching Tags for Skeleton Applications and Extension Packages

When creating additional extension packages within a skeleton application, the tag of the extension package must match the skeleton application's tag. For example:

  • If you create a skeleton application using legacy-v1:
npm init @rancher/extension@legacy-v1 my-app

Any subsequent packages must also use the legacy-v1 tag:

npm init @rancher/extension@legacy-v1 another-extension
  • If you create a skeleton application using legacy-v2:
npm init @rancher/extension@legacy-v2 my-app

Any subsequent packages must use the legacy-v2 tag:

npm init @rancher/extension@legacy-v2 another-extension

Logic Behind the init Script

When you run this command, the init script creates a skeleton application along with an extension package. By default, both the skeleton application and the extension package will have the same name (my-app in this case).

  • If you want the skeleton application to have a different name than the extension package, you can use the --app-name (or -a) option:
npm init @rancher/extension@legacy-v2 new-extension --app-name my-app

This will create a skeleton application named my-app and an extension package named new-extension.

  • If you are already within a skeleton application and want to create another extension package within the same application, simply run the same command:
npm init @rancher/extension@legacy-v2 another-extension

In this case, only a new extension package (another-extension) will be created under the existing skeleton application. No additional skeleton application will be generated.

  • If you only want to create the skeleton application without any extension package, you can use the --skeleton-only (or -s) option:
npm init @rancher/extension@legacy-v2 my-app --skeleton-only

This will create only the skeleton application, and you can later add extension packages as needed.

This flexibility allows you to structure your development environment based on your specific needs, whether you're starting fresh or adding to an existing setup.

Compatibility Note

When building multiple extensions, ensure that all packages and the skeleton application share the same tag. The Node.js version required depends on the tag, as outlined in the prerequisites section. Matching tags and Node.js versions is critical to avoid compatibility issues.

Configuring an Extension

Replace the contents of the file ./pkg/my-app/index.ts with:

import { importTypes } from '@rancher/auto-import';
import { IPlugin } from '@shell/core/types';
import extensionRouting from './routing/extension-routing';

// Init the package
export default function (plugin: IPlugin) {
// Auto-import model, detail, edit from the folders
importTypes(plugin);

// Provide extension metadata from package.json
// it will grab information such as `name` and `description`
plugin.metadata = require('./package.json');

// Load a product
plugin.addProduct(require('./product'));

// Add Vue Routes
plugin.addRoutes(extensionRouting);
}

Next, create a new file ./pkg/my-app/product.ts with this content:

import { IPlugin } from '@shell/core/types';

export function init($plugin: IPlugin, store: any) {
const YOUR_PRODUCT_NAME = 'myProductName';
const BLANK_CLUSTER = '_';

const { product } = $plugin.DSL(store, YOUR_PRODUCT_NAME);

product({
icon: 'gear',
inStore: 'management',
weight: 100,
to: {
name: `${YOUR_PRODUCT_NAME}-c-cluster`,
path: `/${YOUR_PRODUCT_NAME}/c/:cluster/dashboard`,
params: {
product: YOUR_PRODUCT_NAME,
cluster: BLANK_CLUSTER,
pkg: YOUR_PRODUCT_NAME,
},
},
});
}

And finally create a file + folder /routing/extension-routing.js with the content:

// Don't forget to create a VueJS page called index.vue in the /pages folder!!!
import Dashboard from '../pages/index.vue';

const BLANK_CLUSTER = '_';
const YOUR_PRODUCT_NAME = 'myProductName';

const routes = [
{
name: `${YOUR_PRODUCT_NAME}-c-cluster`,
path: `/${YOUR_PRODUCT_NAME}/c/:cluster`,
component: Dashboard,
meta: {
product: YOUR_PRODUCT_NAME,
cluster: BLANK_CLUSTER,
pkg: YOUR_PRODUCT_NAME,
},
},
];

export default routes;

Running the App

We've created a bare bones extension and exposed a new 'product' that will appear in the top-level slide-in menu. At this stage, it does nothing other than that!

You should now be able to run the UI again with:

API=<Rancher Backend URL> yarn dev

Open a web browser to https://127.0.0.1:8005 and you'll see a new 'MyProductName' nav item in the top-level slide-in menu.

MyProductName Nav Item

Note: You should be able to make changes to the extension and the UI will hot-reload and update in the browser.

To further develop a product, add new pages and add new types here's an example.

Building the Extension

Up until now, we've run the extension inside of the skeleton application - this is the developer workflow.

To build the extension so we can use it independently, run:

yarn build-pkg my-app

This will build the extension as a Vue library and the built extension will be placed in the dist-pkg folder.

Loading Into Rancher

Prevent loading your extension in dev mode

When we run API=<Rancher Backend URL> yarn dev, our test extension will be automatically loaded into the application - this allows us to develop the extension with hot-reloading. To test loading the extension dynamically, we can update configuration to tell Rancher not to include our extension.

To do this, edit the file vue.config.js in the root my-app folder, and add the name of the package you want to exclude, such as:

const config = require('@rancher/shell/vue.config');

module.exports = config(__dirname, {
excludes: ['my-app'],
});

Now restart your app by running the UI again with:

API=<Rancher Backend URL> yarn dev

Open a web browser to https://127.0.0.1:8005 and you'll see that the Example nav item is not present - since the extension was not loaded.

Note: You need to be an admin user to test Extensions in the Rancher UI

Test built extension by doing a Developer load

To enable Developer load in the UI, you should go to the user avatar in the top-right and go to Preferences. Under Advanced Features, check the Enable Extension developer features checkbox.

Preferences

Extension Developer Features

Now we need to serve the built package locally by running the following:

yarn serve-pkgs

This will start a small web server (on port 4500) that serves up the contents of the dist-pkg folder. It will output which extensions are being served up - in our case you should see output like that below - it shows the URLs to use for each of the available extensions.

Serving catalog on http://127.0.0.1:4500

Serving packages:

my-app-0.1.0 available at: http://127.0.0.1:4500/my-app-0.1.0/my-app-0.1.0.umd.min.js

Now jump back into the UI and bring in the slide-in menu (click on the hamburger menu in the top-left) and click on 'Extensions'.

Developer Load

Go to the three dot menu and select 'Developer load' - you'll get a dialog allowing you to load the extension into the UI.

Developer Load Modal

In the top input box Extension URL, enter:

https://127.0.0.1:8005/pkg/my-app-0.1.0/my-app-0.1.0.umd.min.js

Press 'Load' and the extension will be loaded, you should see a notification telling you the extension was loaded and if you bring in the side menu again, you should see the Example nav item there now.

This illustrates dynamically loading an extension.

You'll notice that if you reload the Rancher UI, the extension is not persistent and will need to be added again. You can make it persistent by checking the Persist extension by creating custom resource checkbox in the Developer Load dialog.

Creating a Release

Creating a Release for your extension is the official avenue for loading extensions into any Rancher instance. As mentioned in the Introduction, the extension can be packaged into a Helm chart and added as a Helm repository to be easily accessible from your Rancher Manager.

We have created workflows for Github Actions which will automatically build, package, and release your extension as a Helm chart for use within your Github repository, and an Extension Catalog Image (ECI) which is published into a specified container registry (ghcr.io by default). Depending on the use case, you can utilize the Github repository as a Helm repository endpoint which we can use to consume the chart in Rancher, or you can import the ECI into the Extension Catalog list and serve the Helm charts locally.

WARNING: When using the provided Github workflows, the base skeleton application name (Found in the root level package.json) MUST be unique when compared with any extension packages found in ./pkg/*. If an extension package name matches the base skeleton name the workflow will fail due to the "Parse Extension Name" step found in both the "Build and Release Extension Charts" and "Build and release Extension Catalog Image to registry" workflows.

Note: GitLab support is offered through leverging the ECI build. For configuration instructions, follow the setps in the Gitlab Integration section.

Note: If you wish to build and publish the Helm chart or the ECI manually or with specific configurations, you can follow the steps listed in the Publishing an Extension section.

Release Prerequisites

In order to have a Helm repository you will need to enable Github Pages on your Github repository. Just follow these steps:

  1. Create a branch called gh-pages on your Github repository for the extension

  2. Go to the repository of the extension and click the Settings tab in the top navigation bar.

Repo Settings Tab

  1. Then on the left navigation bar of the settings page click the Pages tab.

Repo Pages Tab

  1. Lastly, select GitHub Actions from the Source dropdown.

Repo Pages Dropdown

Consuming the Helm chart

After releasing the Helm chart you will be able to consume this from the Rancher UI by adding your Helm repository's URL to the App -> Repository list. If you used the automated workflow to release the Helm chart, you can find the URL within your Github repository under the "github-pages" Environment.

The URL should be listed as: https://<organization>.github.io/<repository>

Once the URL has been added to the repository list, the extension should appear within the Extensions page.

Wrap-up

This guide has showed you how to create a skeleton application that helps you develop and test one or more extensions.

We showed how we can develop and test those with hot-reloading in the browser and how we can build our extensions into a package that we can dynamically load into Rancher at runtime. We also went over how to release our extensions as Helm charts using the automated workflow.