This lab will explore more advanced aspects of bundle composition to include bundle inheritance and using folders with multiple files. These features make it easier to manage configuration bundles at scale across many controllers.
CloudBees CI Configuration as Code (CasC) for Controllers allows managing bundle files in folders and allows the use of multiple files for certain bundle file types. In this lab we will split your JCasC configuration (the jenkins.yaml file) into two files and put those files in a jcasc folder to make the configuration files easier to manage.
The items CasC configuration also supports managing multiple files in folders (and sub-folders) which may be very useful when managing many controller items with CloudBees CI CasC. Also, if you are managing items within sub-folders you may want to take advantage of the items root property that allows you to define the root path for item creation as part of individual items yaml files (of course you must ensure the root path exists on the controller).
ops-controller repository in your workshop GitHub Organization, click on the Pull requests link and click on the Bundle Folders pull request. 

bundle.yaml file to use all files in the new jcasc folder as jcasc configuration files, added the credentials.yaml file to the new jcasc folder and moved an updated version of the jenkins.yaml to the new jcasc folder.main branch job of the ops-controller Multibranch pipeline project on your Ops controller.main branch job has completed successfully, navigate to the top level of your Ops controller and refresh the page until you see the bundle version change in the system message (remember we updated the controller-casc-update job to auto-reload the bundle). 

jcasc/01-cbci-casc-workshop-ops-controller.jcasc.credentials.yaml and jcasc/01-cbci-casc-workshop-ops-controller.jcasc.jenkins.yaml; and both prefixed with 01, the id of your bundle and include the name of the folder the configurations files are in. This is done to support including configuration files in folders and sub-folders, and to support bundle inheritance as we will see in the next section.Bundle inheritance allows you to easily share common configuration across numerous controllers. In this lab we will update your Ops controller bundle to extend a parent bundle, providing common configuration and plugins to be shared across all of your organizations’ controllers. First, we will review the contents of the parent base bundle that has already been set-up on Operations Center (and is also the default bundle), and then we will update your Ops controller bundle to use the base bundle as a parent bundle. The base bundle will include Jenkins configuration that enforces best practices across all of the controllers in the CloudBees CI cluster and include a common set of plugins to be used across all controllers.
bundle.yaml for the base bundle (also available in GitHub here ):apiVersion: "1"
id: "base"
version: "1"
description: "Workshop Parent Configuration Bundle"
availabilityPattern: ".*"
jcascMergeStrategy: "override"
jcasc:
  - "jenkins.yaml"
plugins:
  - "plugins.yaml"
catalog:
  - "plugin-catalog.yaml"
jcascMergeStrategy is set to override. JCasC configuration supports different merge strategies, currently limited to errorOnConflict and override. Here, we are specifying that everyones’ controllers use the override merge strategy.errorOnConflict is what existed before merge strategies were added to JCasC and will result in a Jenkins exception when loading a bundle with conflicting configuration; meaning that a child bundle cannot overwrite any of the parent configuration valuesoverride allows for JCasC configuration in a child bundle to override that of the parent bundle.Your may also specify the JCasC merge strategy via the -Dcasc.merge.strategy=override system property.
base bundle jenkins.yaml (also available on GitHub here ):jenkins:
  authorizationStrategy: "cloudBeesRoleBasedAccessControl"
  markupFormatter:
    rawHtml:
      disableSyntaxHighlighting: false
  numExecutors: 0
  projectNamingStrategy:
    pattern:
      description: "All project (job) names must be alphanumeric, lower case, may contain dashes/underscores and contain\
        \ no spaces with a limit of 30 characters and a minimum of 4 characters."
      forceExistingJobs: false
      namePattern: "^[a-z0-9-_]{4,30}$"
  quietPeriod: 0
  systemMessage: "Controller configured using CloudBees CI Base Configuration Bundle"
unclassified:
  buildDiscarders:
    configuredBuildDiscarders:
    - "jobBuildDiscarder"
    - simpleBuildDiscarder:
        discarder:
          logRotator:
            numToKeepStr: "5"
  cloudBeesSCMReporting:
    enabled: true
  gitHubConfiguration:
    apiRateLimitChecker: ThrottleOnOver
  globalDefaultFlowDurabilityLevel:
    durabilityHint: PERFORMANCE_OPTIMIZED
  hibernationConfiguration:
    activities:
    - "build"
    - "web"
    enabled: true
    gracePeriod: 2400
beekeeper:
  enabled: true
  securityWarnings:
    enabledForCore: true
    enabledForPlugins: true
  upgrades:
    autoDowngradePlugins: false
    autoUpgradePlugins: false
notificationConfiguration:
  enabled: true
  router: "operationsCenter"
The parent jenkins.yaml enforces a number of best practices across all managed controllers to include:
Next, let’s review the plugins.yaml that will provide a base set of plugins for all the controllers in our CloudBees CI cluster:
plugins:
- id: antisamy-markup-formatter
- id: cloudbees-casc-client
- id: cloudbees-casc-items-api
- id: cloudbees-casc-items-commons
- id: cloudbees-casc-items-controller
- id: cloudbees-github-reporting
- id: cloudbees-groovy-view
- id: cloudbees-monitoring
- id: cloudbees-pipeline-policies
- id: cloudbees-slack
- id: cloudbees-template
- id: cloudbees-view-creation-filter
- id: cloudbees-workflow-template
- id: cloudbees-workflow-ui
- id: configuration-as-code
- id: git
- id: github-branch-source
- id: managed-master-hibernation
- id: notification-api
- id: operations-center-cloud
- id: operations-center-notification
- id: pipeline-event-step
- id: pipeline-model-extensions
- id: pipeline-stage-view
- id: warnings-ng
- id: workflow-aggregator
- id: workflow-cps-checkpoint
plugin-catalog.yaml that will extend CAP plugins and allow individual controllers to opt-in to their usage.displayName: CloudBees CI Workshop Plugin Catalog
name: cbci-workshop-catalog
type: plugin-catalog
version: '1'
configurations:
- description: Workshop Additional Plugins
  includePlugins:
    pipeline-utility-steps: 
      version: 2.13.0
base bundle, navigate to your ops-controller repository in your workshop GitHub Organization, click on the Pull requests link and click on the Bundle Inheritance pull request. 
bundle.yaml note that we added parent: base and removed the catalog entry. 
jenkins.yaml file link and you will see that much of the configuration has been removed since it will be provided by the parent bundle:quietPeriod under jenkins.systemMessage to 'Jenkins configured using CloudBees CI CasC with controller overrides'.unclassified section deleted everything except for the globallibraries section.headerLabel text to v4.

plugins.yaml file link. The plugin-catalog.yaml has been deleted. Also, all of the plugins have been removed from the plugins.yaml file except for the non-CAP pipeline-utility-steps plugin made available to install via the parent bundle plugin-catalog.yaml configuration. Plugin files are merged so the majority of your controller plugins will now come from the parent defined standard list of plugins. Plugin catalog files are not merged, so we are relying on the parent bundle to defined the available non-CAP plugins. 
main branch job of your ops-controller Multibranch pipeline project on your Ops controller.main branch job has completed successfully, navigate to the top level of your Ops controller, the system message should read - “Jenkins configured using CloudBees CI CasC with controller overrides” signifying that the base bundle has been overridden by your controller specific bundle. 
It takes a minute or two for the bundle files to be checked out, copied, updated and reloaded.
jcasc files: jcasc/01-base.jenkins.yaml, jcasc/02-cbci-casc-workshop-ops-controller.jcasc.credentials.yaml and jcasc/02-cbci-casc-workshop-ops-controller.jcasc.jenkins.yaml. CloudBees CI Configuration as Code (CasC) for Controllers automatically renames all JCasC files by prefixing them with the level of inheritance, the bundle id and their folder structure and then copies them into the jcasc directory. However, in the case of the plugins.yaml, multiple files are merged into one. Also note that the items.yaml file is prefixed and placed in an items folder. 