rancher / dashboard

The Rancher UI
https://rancher.com
Apache License 2.0
450 stars 256 forks source link

Refactor the code that builds the Cluster Explorer side nav #5607

Open catherineluse opened 2 years ago

catherineluse commented 2 years ago

Reason 1: Performance

When the Cluster Explorer loads for the first time, it creates over 300 mutations to the store.

This is an antipattern because we should only use the store to cache data from the back end, or to track changes that affect multiple components that are not close to each other in the DOM. Most state in Vue should be handled within individual components or with events. And this side nav code doesn't even have to do with state - it is just about loading a single component for the first time.

In principle, a single component shouldn't have to mutate the store at all when it loads for the first time. All the logic for building the side nav should be handled within the side nav component itself.

So if this is refactored to avoid mutating the store, it may be faster to load Cluster Explorer for the first time. When I say faster, I mean we could first show a default (mostly empty or with a loading spinner) side nav so the user does't stare at a totally empty screen, then modify it after the schemas are loaded, then modify it again after we do any async calls that we need to do to figure out whether to show links to certain services deployed from helm charts.

Reason 2: Ease of use

I struggle with type-map.js. Here are the two tasks I struggled with recently because type-map.js was so hard to read:

We will have to update this side nav many times in the future. The question is, should it be easy to update, or should it be hard?

Reason 3: Would require a refactor to ever be in a component library

Because the side nav has so many dependencies on Vuex, that means it couldn't be used by other applications. Anything that goes in the component library would have to be self-contained.

Reason 4: We need to allow async calls to affect what is displayed

Currently the code is imperative and is strictly required to run after the schemas are loaded, but before anything else is.

This means we can't wait to show someone a link to a service such as NeuVector in the side nav until we make an async call to ensure the service exists. So we just hardcode a link and assume the service will be there. This leads to a bad UX when the user clicks the link but it's broken because the service is not deployed.

Reason 5: Customization

Kenneth said customers gave feedback that they wish they could fully customize what is seen in the side nav so they can limit their users to a UI that is more focused toward their purpose. The current implementation doesn't allow for a very detailed level of customization.

Objective

If this code is refactored, the goal should be:

Method

Here's what I did to get to the "over 300" number.

Added logs to the parts of type-map.js that mutate the store:

product(inOpt) {
      const opt = {
        name:                product,
        weight:              1,
        inStore:             'cluster',
        removable:           true,
        showClusterSwitcher: true,
        showNamespaceFilter: false,
        public:              true,
        filterMode:          'namespaces',
        ...inOpt
      };

      for ( const k of ['ifHaveGroup', 'ifHaveType'] ) {
        if ( opt[k] ) {
          opt[k] = regexToString(ensureRegex(opt[k]));
        }
      }

      store.commit(`${ module }/product`, opt);
      console.log('TypeMap product mutation');
    },

    basicType(types, group) {
      // Support passing in a map of types and using just the values
      if ( !isArray(types) && types && isObject(types) ) {
        types = Object.values(types);
      }

      store.commit(`${ module }/basicType`, {
        product, types, group
      });
      console.log('TypeMap basicType mutation');
    },

    // Type- and Group-dependent
    groupBy(type, field) {
      store.commit(`${ module }/groupBy`, { type, field });
      console.log('TypeMap groupBy mutation');
    },

    headers(type, headers) {
      headers.forEach((header) => {
        // If on the client, then use the value getter if there is one
        if (process.client && header.getValue) {
          header.value = header.getValue;
        }

        delete header.getValue;
      });

      store.commit(`${ module }/headers`, { type, headers });
      console.log('TypeMap headers mutation');
    },

    hideBulkActions(type, field) {
      store.commit(`${ module }/hideBulkActions`, { type, field });
      console.log('TypeMap hideBulkActions mutation');
    },

    configureType(match, options) {
      store.commit(`${ module }/configureType`, { ...options, match });
      console.log('TypeMap configureType mutation');
    },

    componentForType(match, replace) {
      store.commit(`${ module }/componentForType`, { match, replace });
      console.log('TypeMap componentForType mutation');
    },

    ignoreType(regexOrString) {
      store.commit(`${ module }/ignoreType`, regexOrString);
      console.log('TypeMap ignoreType mutation');
    },

    ignoreGroup(regexOrString) {
      store.commit(`${ module }/ignoreGroup`, regexOrString);
      console.log('TypeMap ignoreGroup mutation');
    },

    weightGroup(input, weight, forBasic) {
      if ( isArray(input) ) {
        store.commit(`${ module }/weightGroup`, {
          groups: input, weight, forBasic
        });
        console.log('TypeMap weightGroup mutation');
      } else {
        store.commit(`${ module }/weightGroup`, {
          group: input, weight, forBasic
        });
        console.log('TypeMap weightGroup mutation');
      }
    },

    setGroupDefaultType(input, defaultType) {
      if ( isArray(input) ) {
        store.commit(`${ module }/setGroupDefaultType`, { groups: input, defaultType });
        console.log('TypeMap setGroupDefaultType mutation');
      } else {
        store.commit(`${ module }/setGroupDefaultType`, { group: input, defaultType });
        console.log('TypeMap setGroupDefaultType mutation');
      }
    },

    weightType(input, weight, forBasic) {
      if ( isArray(input) ) {
        store.commit(`${ module }/weightType`, {
          types: input, weight, forBasic
        });
        console.log('TypeMap weightType mutation');
      } else {
        store.commit(`${ module }/weightType`, {
          type: input, weight, forBasic
        });
        console.log('TypeMap weightType mutation');
      }
    },

    mapGroup(match, replace, weight = 5, continueOnMatch = false) {
      store.commit(`${ module }/mapGroup`, {
        match, replace, weight, continueOnMatch
      });
      console.log('TypeMap mapGroup mutation');
    },

    mapType(match, replace, weight = 5, continueOnMatch = false) {
      store.commit(`${ module }/mapType`, {
        match, replace, weight, continueOnMatch
      });
      console.log('TypeMap mapType mutation');
    },

    moveType(match, group, weight = 5, continueOnMatch = false) {
      store.commit(`${ module }/moveType`, {
        match, group, weight,
      });
      console.log('TypeMap moveType mutation');
    },

    virtualType(obj) {
      store.commit(`${ module }/virtualType`, { product, obj });
      console.log('TypeMap virtualType mutation');
    },

    spoofedType(obj) {
      store.commit(`${ module }/spoofedType`, { product, obj });
      console.log('TypeMap spoofedType mutation');
    }
  };

Results of loading the side nav for the first time:

type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:312 TypeMap spoofedType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:295 TypeMap mapType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:233 TypeMap componentForType mutation
type-map.js?8c6e:233 TypeMap componentForType mutation
type-map.js?8c6e:233 TypeMap componentForType mutation
type-map.js?8c6e:233 TypeMap componentForType mutation
type-map.js?8c6e:233 TypeMap componentForType mutation
type-map.js?8c6e:233 TypeMap componentForType mutation
type-map.js?8c6e:233 TypeMap componentForType mutation
type-map.js?8c6e:233 TypeMap componentForType mutation
type-map.js?8c6e:233 TypeMap componentForType mutation
type-map.js?8c6e:233 TypeMap componentForType mutation
type-map.js?8c6e:233 TypeMap componentForType mutation
type-map.js?8c6e:233 TypeMap componentForType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:256 TypeMap weightGroup mutation
type-map.js?8c6e:256 TypeMap weightGroup mutation
type-map.js?8c6e:256 TypeMap weightGroup mutation
type-map.js?8c6e:256 TypeMap weightGroup mutation
type-map.js?8c6e:280 TypeMap weightType mutation
7type-map.js?8c6e:233 TypeMap componentForType mutation
type-map.js?8c6e:238 TypeMap ignoreType mutation
type-map.js?8c6e:238 TypeMap ignoreType mutation
type-map.js?8c6e:238 TypeMap ignoreType mutation
type-map.js?8c6e:238 TypeMap ignoreType mutation
type-map.js?8c6e:238 TypeMap ignoreType mutation
type-map.js?8c6e:238 TypeMap ignoreType mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:266 TypeMap setGroupDefaultType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:238 TypeMap ignoreType mutation
type-map.js?8c6e:238 TypeMap ignoreType mutation
type-map.js?8c6e:238 TypeMap ignoreType mutation
type-map.js?8c6e:238 TypeMap ignoreType mutation
type-map.js?8c6e:238 TypeMap ignoreType mutation
type-map.js?8c6e:238 TypeMap ignoreType mutation
type-map.js?8c6e:238 TypeMap ignoreType mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:288 TypeMap mapGroup mutation
type-map.js?8c6e:295 TypeMap mapType mutation
type-map.js?8c6e:295 TypeMap mapType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:312 TypeMap spoofedType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:204 TypeMap groupBy mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:312 TypeMap spoofedType mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:312 TypeMap spoofedType mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:256 TypeMap weightGroup mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:312 TypeMap spoofedType mutation
type-map.js?8c6e:312 TypeMap spoofedType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:295 TypeMap mapType mutation
type-map.js?8c6e:295 TypeMap mapType mutation
type-map.js?8c6e:295 TypeMap mapType mutation
type-map.js?8c6e:295 TypeMap mapType mutation
type-map.js?8c6e:295 TypeMap mapType mutation
type-map.js?8c6e:295 TypeMap mapType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:280 TypeMap weightType mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:186 TypeMap product mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:307 TypeMap virtualType mutation
type-map.js?8c6e:198 TypeMap basicType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:228 TypeMap configureType mutation
type-map.js?8c6e:218 TypeMap headers mutation
type-map.js?8c6e:223 TypeMap hideBulkActions mutation

Example Config

This is an example output configuration resulting from the >300 mutations. I wish it was easier to predict what this final output looks like.

[
   {
      "name":"cluster",
      "label":"Cluster",
      "weight":99,
      "defaultType":"__vue_devtool_undefined__",
      "children":[
         {
            "label":"Cluster Dashboard",
            "labelDisplay":"Cluster Dashboard",
            "mode":"basic",
            "count":"__vue_devtool_undefined__",
            "exact":true,
            "namespaced":false,
            "route":{
               "name":"c-cluster-explorer",
               "params":{
                  "cluster":"local",
                  "product":"explorer"
               }
            },
            "name":"cluster-dashboard",
            "weight":100,
            "overview":true
         },
         {
            "label":"Projects/Namespaces",
            "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>Projects/Namespaces",
            "mode":"basic",
            "count":"__vue_devtool_undefined__",
            "exact":true,
            "namespaced":false,
            "route":{
               "name":"c-cluster-product-projectsnamespaces",
               "params":{
                  "cluster":"local",
                  "product":"explorer"
               }
            },
            "name":"projects-namespaces",
            "weight":98,
            "overview":false
         },
         {
            "label":"Nodes",
            "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>Nodes",
            "mode":"basic",
            "count":1,
            "exact":false,
            "namespaced":false,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"node"
               }
            },
            "name":"node",
            "weight":0,
            "overview":false
         },
         {
            "label":"Cluster Members",
            "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>Cluster Members",
            "mode":"basic",
            "count":"__vue_devtool_undefined__",
            "exact":true,
            "namespaced":false,
            "route":{
               "name":"c-cluster-product-members",
               "params":{
                  "cluster":"local",
                  "product":"explorer"
               }
            },
            "name":"cluster-members",
            "weight":-1,
            "overview":false
         }
      ]
   },
   {
      "name":"workload",
      "label":"Workload",
      "weight":98,
      "defaultType":"__vue_devtool_undefined__",
      "children":[
         {
            "label":" Workloads ",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i> Workloads ",
            "mode":"basic",
            "count":"__vue_devtool_undefined__",
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "resource":"workload",
                  "cluster":"local",
                  "product":"explorer"
               }
            },
            "name":"workload",
            "weight":99,
            "overview":true
         },
         {
            "label":"CronJobs",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>CronJobs",
            "mode":"basic",
            "count":0,
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"batch.cronjob"
               }
            },
            "name":"batch.cronjob",
            "weight":0,
            "overview":false
         },
         {
            "label":"DaemonSets",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>DaemonSets",
            "mode":"basic",
            "count":0,
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"apps.daemonset"
               }
            },
            "name":"apps.daemonset",
            "weight":0,
            "overview":false
         },
         {
            "label":"Deployments",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Deployments",
            "mode":"basic",
            "count":3,
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"apps.deployment"
               }
            },
            "name":"apps.deployment",
            "weight":0,
            "overview":false
         },
         {
            "label":"Jobs",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Jobs",
            "mode":"basic",
            "count":0,
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"batch.job"
               }
            },
            "name":"batch.job",
            "weight":0,
            "overview":false
         },
         {
            "label":"StatefulSets",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>StatefulSets",
            "mode":"basic",
            "count":0,
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"apps.statefulset"
               }
            },
            "name":"apps.statefulset",
            "weight":0,
            "overview":false
         },
         {
            "label":"Pods",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Pods",
            "mode":"basic",
            "count":4,
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"pod"
               }
            },
            "name":"pod",
            "weight":-1,
            "overview":false
         }
      ]
   },
   {
      "name":"apps",
      "label":"Apps",
      "children":[
         {
            "label":"Charts",
            "labelDisplay":"<i class=\"icon icon-fw icon-compass\"></i>Charts",
            "mode":"basic",
            "count":"__vue_devtool_undefined__",
            "exact":false,
            "namespaced":false,
            "route":{
               "name":"c-cluster-apps-charts",
               "params":{
                  "cluster":"local",
                  "product":"apps"
               }
            },
            "name":"charts",
            "weight":100,
            "overview":false
         },
         {
            "label":"Installed Apps",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Installed Apps",
            "mode":"basic",
            "count":0,
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"apps",
                  "cluster":"local",
                  "resource":"catalog.cattle.io.app"
               }
            },
            "name":"catalog.cattle.io.app",
            "weight":99,
            "overview":false
         },
         {
            "label":"Repositories",
            "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>Repositories",
            "mode":"basic",
            "count":5,
            "exact":false,
            "namespaced":false,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"apps",
                  "cluster":"local",
                  "resource":"catalog.cattle.io.clusterrepo"
               }
            },
            "name":"catalog.cattle.io.clusterrepo",
            "weight":0,
            "overview":false
         },
         {
            "label":"Recent Operations",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Recent Operations",
            "mode":"basic",
            "count":0,
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"apps",
                  "cluster":"local",
                  "resource":"catalog.cattle.io.operation"
               }
            },
            "name":"catalog.cattle.io.operation",
            "weight":0,
            "overview":false
         }
      ],
      "weight":97
   },
   {
      "name":"serviceDiscovery",
      "label":"Service Discovery",
      "weight":96,
      "defaultType":"service",
      "children":[
         {
            "label":"HorizontalPodAutoscalers",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>HorizontalPodAutoscalers",
            "mode":"basic",
            "count":0,
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"autoscaling.horizontalpodautoscaler"
               }
            },
            "name":"autoscaling.horizontalpodautoscaler",
            "weight":0,
            "overview":false
         },
         {
            "label":"Ingresses",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Ingresses",
            "mode":"basic",
            "count":0,
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"networking.k8s.io.ingress"
               }
            },
            "name":"networking.k8s.io.ingress",
            "weight":0,
            "overview":false
         },
         {
            "label":"NetworkPolicies",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>NetworkPolicies",
            "mode":"basic",
            "count":0,
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"networking.k8s.io.networkpolicy"
               }
            },
            "name":"networking.k8s.io.networkpolicy",
            "weight":0,
            "overview":false
         },
         {
            "label":"Services",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Services",
            "mode":"basic",
            "count":1,
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"service"
               }
            },
            "name":"service",
            "weight":0,
            "overview":false
         }
      ]
   },
   {
      "name":"storage",
      "label":"Storage",
      "weight":95,
      "defaultType":"__vue_devtool_undefined__",
      "children":[
         {
            "label":"PersistentVolumes",
            "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>PersistentVolumes",
            "mode":"basic",
            "count":0,
            "exact":false,
            "namespaced":false,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"persistentvolume"
               }
            },
            "name":"persistentvolume",
            "weight":0,
            "overview":false
         },
         {
            "label":"StorageClasses",
            "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>StorageClasses",
            "mode":"basic",
            "count":1,
            "exact":false,
            "namespaced":false,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"storage.k8s.io.storageclass"
               }
            },
            "name":"storage.k8s.io.storageclass",
            "weight":0,
            "overview":false
         },
         {
            "label":"ConfigMaps",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>ConfigMaps",
            "mode":"basic",
            "count":7,
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"configmap"
               }
            },
            "name":"configmap",
            "weight":0,
            "overview":false
         },
         {
            "label":"PersistentVolumeClaims",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>PersistentVolumeClaims",
            "mode":"basic",
            "count":0,
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"persistentvolumeclaim"
               }
            },
            "name":"persistentvolumeclaim",
            "weight":0,
            "overview":false
         },
         {
            "label":"Secrets",
            "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Secrets",
            "mode":"basic",
            "count":7,
            "exact":false,
            "namespaced":true,
            "route":{
               "name":"c-cluster-product-resource",
               "params":{
                  "product":"explorer",
                  "cluster":"local",
                  "resource":"secret"
               }
            },
            "name":"secret",
            "weight":0,
            "overview":false
         }
      ]
   },
   {
      "name":"legacy",
      "label":"Legacy",
      "children":[
         {
            "label":"Alerts",
            "labelDisplay":"Alerts",
            "mode":"basic",
            "count":"__vue_devtool_undefined__",
            "exact":true,
            "namespaced":true,
            "route":{
               "name":"c-cluster-legacy-pages-page",
               "params":{
                  "page":"alerts",
                  "cluster":"local",
                  "product":"legacy"
               }
            },
            "name":"v1-alerts",
            "weight":111,
            "overview":false
         },
         {
            "label":"Catalogs",
            "labelDisplay":"Catalogs",
            "mode":"basic",
            "count":"__vue_devtool_undefined__",
            "exact":true,
            "namespaced":true,
            "route":{
               "name":"c-cluster-legacy-pages-page",
               "params":{
                  "page":"catalogs",
                  "cluster":"local",
                  "product":"legacy"
               }
            },
            "name":"v1-catalogs",
            "weight":111,
            "overview":false
         },
         {
            "label":"CIS Scans",
            "labelDisplay":"CIS Scans",
            "mode":"basic",
            "count":"__vue_devtool_undefined__",
            "exact":true,
            "namespaced":true,
            "route":{
               "name":"c-cluster-legacy-pages-page",
               "params":{
                  "page":"cis",
                  "cluster":"local",
                  "product":"legacy"
               }
            },
            "name":"v1-cis-scans",
            "weight":111,
            "overview":false
         },
         {
            "label":"Notifiers",
            "labelDisplay":"Notifiers",
            "mode":"basic",
            "count":"__vue_devtool_undefined__",
            "exact":true,
            "namespaced":true,
            "route":{
               "name":"c-cluster-legacy-pages-page",
               "params":{
                  "page":"notifiers",
                  "cluster":"local",
                  "product":"legacy"
               }
            },
            "name":"v1-notifiers",
            "weight":111,
            "overview":false
         },
         {
            "label":"Project",
            "labelDisplay":"Project",
            "mode":"basic",
            "count":"__vue_devtool_undefined__",
            "exact":true,
            "namespaced":true,
            "route":{
               "name":"c-cluster-legacy-project",
               "params":{
                  "cluster":"local",
                  "product":"legacy"
               }
            },
            "name":"v1-project-overview",
            "weight":105,
            "overview":false
         }
      ],
      "weight":80
   },
   {
      "name":"NeuVector",
      "label":"NeuVector",
      "children":[
         {
            "label":"Overview",
            "labelDisplay":"Overview",
            "mode":"basic",
            "count":"__vue_devtool_undefined__",
            "exact":true,
            "namespaced":false,
            "route":{
               "name":"c-cluster-neuvector",
               "params":{
                  "cluster":"local",
                  "product":"NeuVector"
               }
            },
            "name":"neuvector-overview",
            "weight":106,
            "overview":true
         }
      ],
      "weight":1
   },
   {
      "name":"inUse",
      "label":"More Resources",
      "weight":0,
      "defaultType":"__vue_devtool_undefined__",
      "children":[
         {
            "name":"admission",
            "label":"Admission",
            "weight":0,
            "defaultType":"__vue_devtool_undefined__",
            "children":[
               {
                  "label":"MutatingWebhookConfigurations",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>MutatingWebhookConfigurations",
                  "mode":"used",
                  "count":2,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"admissionregistration.k8s.io.mutatingwebhookconfiguration"
                     }
                  },
                  "name":"admissionregistration.k8s.io.mutatingwebhookconfiguration",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"ValidatingWebhookConfigurations",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>ValidatingWebhookConfigurations",
                  "mode":"used",
                  "count":3,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"admissionregistration.k8s.io.validatingwebhookconfiguration"
                     }
                  },
                  "name":"admissionregistration.k8s.io.validatingwebhookconfiguration",
                  "weight":0,
                  "overview":false
               }
            ]
         },
         {
            "name":"API",
            "label":"API",
            "weight":0,
            "defaultType":"__vue_devtool_undefined__",
            "children":[
               {
                  "label":"APIServices",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>APIServices",
                  "mode":"used",
                  "count":46,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"apiregistration.k8s.io.apiservice"
                     }
                  },
                  "name":"apiregistration.k8s.io.apiservice",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"CustomResourceDefinitions",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>CustomResourceDefinitions",
                  "mode":"used",
                  "count":132,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"apiextensions.k8s.io.customresourcedefinition"
                     }
                  },
                  "name":"apiextensions.k8s.io.customresourcedefinition",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"FlowSchemas",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>FlowSchemas",
                  "mode":"used",
                  "count":12,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"flowcontrol.apiserver.k8s.io.flowschema"
                     }
                  },
                  "name":"flowcontrol.apiserver.k8s.io.flowschema",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"PriorityLevelConfigurations",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>PriorityLevelConfigurations",
                  "mode":"used",
                  "count":8,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"flowcontrol.apiserver.k8s.io.prioritylevelconfiguration"
                     }
                  },
                  "name":"flowcontrol.apiserver.k8s.io.prioritylevelconfiguration",
                  "weight":0,
                  "overview":false
               }
            ]
         },
         {
            "name":"apps",
            "label":"Apps",
            "weight":0,
            "defaultType":"__vue_devtool_undefined__",
            "children":[
               {
                  "label":"Deployments",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Deployments",
                  "mode":"used",
                  "count":3,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"apps.deployment"
                     }
                  },
                  "name":"apps.deployment",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"ReplicaSets",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>ReplicaSets",
                  "mode":"used",
                  "count":3,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"apps.replicaset"
                     }
                  },
                  "name":"apps.replicaset",
                  "weight":0,
                  "overview":false
               }
            ]
         },
         {
            "name":"clusterProvisioning",
            "label":"Cluster Provisioning",
            "weight":0,
            "defaultType":"__vue_devtool_undefined__",
            "children":[
               {
                  "label":"Clusters",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>Clusters",
                  "mode":"used",
                  "count":1,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"provisioning.cattle.io.cluster"
                     }
                  },
                  "name":"provisioning.cattle.io.cluster",
                  "weight":0,
                  "overview":false
               }
            ]
         },
         {
            "name":"core",
            "label":"Core",
            "weight":0,
            "defaultType":"__vue_devtool_undefined__",
            "children":[
               {
                  "label":"Nodes",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>Nodes",
                  "mode":"used",
                  "count":1,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"node"
                     }
                  },
                  "name":"node",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"ConfigMaps",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>ConfigMaps",
                  "mode":"used",
                  "count":7,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"configmap"
                     }
                  },
                  "name":"configmap",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"Endpoints",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Endpoints",
                  "mode":"used",
                  "count":1,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"endpoints"
                     }
                  },
                  "name":"endpoints",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"Events",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Events",
                  "mode":"used",
                  "count":1,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"event"
                     }
                  },
                  "name":"event",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"Pods",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Pods",
                  "mode":"used",
                  "count":4,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"pod"
                     }
                  },
                  "name":"pod",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"ResourceQuotas",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>ResourceQuotas",
                  "mode":"used",
                  "count":1,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"resourcequota"
                     }
                  },
                  "name":"resourcequota",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"Secrets",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Secrets",
                  "mode":"used",
                  "count":7,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"secret"
                     }
                  },
                  "name":"secret",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"ServiceAccounts",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>ServiceAccounts",
                  "mode":"used",
                  "count":7,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"serviceaccount"
                     }
                  },
                  "name":"serviceaccount",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"Services",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Services",
                  "mode":"used",
                  "count":1,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"service"
                     }
                  },
                  "name":"service",
                  "weight":0,
                  "overview":false
               }
            ]
         },
         {
            "name":"Discovery",
            "label":"Discovery",
            "weight":0,
            "defaultType":"__vue_devtool_undefined__",
            "children":[
               {
                  "label":"EndpointSlices",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>EndpointSlices",
                  "mode":"used",
                  "count":1,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"discovery.k8s.io.endpointslice"
                     }
                  },
                  "name":"discovery.k8s.io.endpointslice",
                  "weight":0,
                  "overview":false
               }
            ]
         },
         {
            "name":"Fleet",
            "label":"Fleet",
            "weight":0,
            "defaultType":"__vue_devtool_undefined__",
            "children":[
               {
                  "label":"Contents",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>Contents",
                  "mode":"used",
                  "count":1,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"fleet.cattle.io.content"
                     }
                  },
                  "name":"fleet.cattle.io.content",
                  "weight":0,
                  "overview":false
               }
            ]
         },
         {
            "name":"Rancher",
            "label":"Rancher",
            "weight":0,
            "defaultType":"__vue_devtool_undefined__",
            "children":[
               {
                  "label":"APIServices",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>APIServices",
                  "mode":"used",
                  "count":1,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"management.cattle.io.apiservice"
                     }
                  },
                  "name":"management.cattle.io.apiservice",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"Authentication Providers",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>Authentication Providers",
                  "mode":"used",
                  "count":14,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"management.cattle.io.authconfig"
                     }
                  },
                  "name":"management.cattle.io.authconfig",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"Catalogs",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>Catalogs",
                  "mode":"used",
                  "count":3,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"management.cattle.io.catalog"
                     }
                  },
                  "name":"management.cattle.io.catalog",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"DynamicSchemas",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>DynamicSchemas",
                  "mode":"used",
                  "count":21,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"management.cattle.io.dynamicschema"
                     }
                  },
                  "name":"management.cattle.io.dynamicschema",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"GlobalRoleBindings",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>GlobalRoleBindings",
                  "mode":"used",
                  "count":3,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"management.cattle.io.globalrolebinding"
                     }
                  },
                  "name":"management.cattle.io.globalrolebinding",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"KontainerDrivers",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>KontainerDrivers",
                  "mode":"used",
                  "count":11,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"management.cattle.io.kontainerdriver"
                     }
                  },
                  "name":"management.cattle.io.kontainerdriver",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"Mgmt Clusters",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>Mgmt Clusters",
                  "mode":"used",
                  "count":1,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"management.cattle.io.cluster"
                     }
                  },
                  "name":"management.cattle.io.cluster",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"NodeDrivers",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>NodeDrivers",
                  "mode":"used",
                  "count":20,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"management.cattle.io.nodedriver"
                     }
                  },
                  "name":"management.cattle.io.nodedriver",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"PodSecurityPolicyTemplates",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>PodSecurityPolicyTemplates",
                  "mode":"used",
                  "count":3,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"management.cattle.io.podsecuritypolicytemplate"
                     }
                  },
                  "name":"management.cattle.io.podsecuritypolicytemplate",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"Repositories",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>Repositories",
                  "mode":"used",
                  "count":5,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"catalog.cattle.io.clusterrepo"
                     }
                  },
                  "name":"catalog.cattle.io.clusterrepo",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"UserAttributes",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>UserAttributes",
                  "mode":"used",
                  "count":2,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"management.cattle.io.userattribute"
                     }
                  },
                  "name":"management.cattle.io.userattribute",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"Workspaces",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>Workspaces",
                  "mode":"used",
                  "count":2,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"management.cattle.io.fleetworkspace"
                     }
                  },
                  "name":"management.cattle.io.fleetworkspace",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"ClusterAlertGroups",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>ClusterAlertGroups",
                  "mode":"used",
                  "count":5,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"management.cattle.io.clusteralertgroup"
                     }
                  },
                  "name":"management.cattle.io.clusteralertgroup",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"ClusterAlertRules",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>ClusterAlertRules",
                  "mode":"used",
                  "count":14,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"management.cattle.io.clusteralertrule"
                     }
                  },
                  "name":"management.cattle.io.clusteralertrule",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"ClusterRegistrationTokens",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>ClusterRegistrationTokens",
                  "mode":"used",
                  "count":1,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"management.cattle.io.clusterregistrationtoken"
                     }
                  },
                  "name":"management.cattle.io.clusterregistrationtoken",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"Nodes",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Nodes",
                  "mode":"used",
                  "count":1,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"management.cattle.io.node"
                     }
                  },
                  "name":"management.cattle.io.node",
                  "weight":0,
                  "overview":false
               }
            ]
         },
         {
            "name":"RBAC",
            "label":"RBAC",
            "weight":0,
            "defaultType":"__vue_devtool_undefined__",
            "children":[
               {
                  "label":"ClusterRoleBindings",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>ClusterRoleBindings",
                  "mode":"used",
                  "count":90,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"rbac.authorization.k8s.io.clusterrolebinding"
                     }
                  },
                  "name":"rbac.authorization.k8s.io.clusterrolebinding",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"ClusterRoles",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>ClusterRoles",
                  "mode":"used",
                  "count":127,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"rbac.authorization.k8s.io.clusterrole"
                     }
                  },
                  "name":"rbac.authorization.k8s.io.clusterrole",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"RoleBindings",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>RoleBindings",
                  "mode":"used",
                  "count":9,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"rbac.authorization.k8s.io.rolebinding"
                     }
                  },
                  "name":"rbac.authorization.k8s.io.rolebinding",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"Roles",
                  "labelDisplay":"<i class=\"icon icon-fw icon-folder\"></i>Roles",
                  "mode":"used",
                  "count":4,
                  "exact":false,
                  "namespaced":true,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"rbac.authorization.k8s.io.role"
                     }
                  },
                  "name":"rbac.authorization.k8s.io.role",
                  "weight":0,
                  "overview":false
               }
            ]
         },
         {
            "name":"Scheduling",
            "label":"Scheduling",
            "weight":0,
            "defaultType":"__vue_devtool_undefined__",
            "children":[
               {
                  "label":"PriorityClasses",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>PriorityClasses",
                  "mode":"used",
                  "count":2,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"scheduling.k8s.io.priorityclass"
                     }
                  },
                  "name":"scheduling.k8s.io.priorityclass",
                  "weight":0,
                  "overview":false
               }
            ]
         },
         {
            "name":"Storage",
            "label":"Storage",
            "weight":0,
            "defaultType":"__vue_devtool_undefined__",
            "children":[
               {
                  "label":"CSINodes",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>CSINodes",
                  "mode":"used",
                  "count":1,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"storage.k8s.io.csinode"
                     }
                  },
                  "name":"storage.k8s.io.csinode",
                  "weight":0,
                  "overview":false
               },
               {
                  "label":"StorageClasses",
                  "labelDisplay":"<i class=\"icon icon-fw icon-globe\"></i>StorageClasses",
                  "mode":"used",
                  "count":1,
                  "exact":false,
                  "namespaced":false,
                  "route":{
                     "name":"c-cluster-product-resource",
                     "params":{
                        "product":"explorer",
                        "cluster":"local",
                        "resource":"storage.k8s.io.storageclass"
                     }
                  },
                  "name":"storage.k8s.io.storageclass",
                  "weight":0,
                  "overview":false
               }
            ]
         }
      ]
   }
]
catherineluse commented 1 year ago

Marking as size/20 due to the huge amount of code in shell/config/product that would be affected if all the imperative config code there was made declarative.

richard-cox commented 1 year ago

getGroups is covered by https://github.com/rancher/dashboard/issues/7773