Advanced CasC bundle configuration

7 minute read

Composing CasC bundles

There are several options for composing CasC bundles. You can compose:

Single bundle

A single CasC bundle is composed of individual YAML files stored in a folder and the bundle is deployed to the operations center.

Example single bundle

/oc-bundles └── bundle-1 ├── bundle.yaml ├── jenkins.yaml ├── plugins.yaml ├── plugin-catalog.yaml ├── items.yaml ├── rbac.yaml └── variables.yaml

Single bundle with folders and subfolders

Configuration settings can be stored in individual YAML files, and the files stored within folders and subfolders in the bundle.

CloudBees recommends that each YAML file contain only unique configuration elements that do not override configuration elements in other YAML files.

The Plugin Catalog does not support storing configuration settings in individual YAML files.

Avoiding YAML file overrides

An override in a YAML file does not include the whole file but properties within the YAML file. For example, if items1.yaml defines a property and items2.yaml defines the same property then:

  • Properties not defined in items2.yaml will have the same value as properties from items1.yaml.

  • Properties defined in items2.yaml will override the value of properties from items1.yaml.

  • The override behavior is the same for rbac.yaml files.

  • For the variables.yaml files, the override occurs on the unique value of the variable so that the last value prevails.

To prevent undesired item overrides, YAML files are read as follows:

  • If files are listed in the section, they are read in that order, so the last file overrides the first.

  • If the folder containing the files is referenced instead of listing them, the files are read in alphanumeric order.

  • If there is inheritance, child files override their parent files.

Example bundle with folders

In this example, a configurations folder contains individual YAML files:

/oc-bundles └── bundle-1 ├── bundle.yaml ├── configurations │ ├── jenkins.yaml │ └── security.yaml ├── plugins.yaml ├── plugin-catalog.yaml ├── items.yaml ├── rbac.yaml └── variables.yaml

The bundle.yaml file lists each individual YAML file:

id: "bundle-1" version: "1" apiVersion: "1" description: "My CloudBees Configuration as Code (CasC) bundle" jcasc: - "configurations/jenkins.yaml" - "configurations/security.yaml" plugins: - "plugins.yaml" catalog: - "plugin-catalog.yaml" items: - "items.yaml" rbac: - "rbac.yaml" variables: - "variables.yaml"

Example bundle with subfolders

In this example, the configurations folder contains a jenkins subfolder, and the jenkins subfolder contains the individual YAML files:

/oc-bundles └── bundle-1 ├── bundle.yaml ├── configurations │ └── jenkins │ └── jenkins.yaml │ └── security.yaml ├── plugins.yaml ├── plugin-catalog.yaml ├── items.yaml ├── rbac.yaml └── variables.yaml

This allows you to add or remove YAML files from the subfolder without requiring that you update the bundle.yaml file:

id: "bundle-1" version: "1" apiVersion: "1" description: "My CloudBees Configuration as Code (CasC) bundle" jcasc: - "configurations/jenkins/" plugins: - "plugins.yaml" catalog: - "plugin-catalog.yaml" items: - "items.yaml" rbac: - "rbac.yaml" variables: - "variables.yaml"

Multiple bundles

Multiple bundles can also be deployed to the operations center.

Example folders for multiple bundles

/oc-bundles ├── bundle-1 │ ├── bundle.yaml │ ├── jenkins.yaml │ ├── plugins.yaml │ ├── plugin-catalog.yaml │ ├── items.yaml │ ├── rbac.yaml │ └── variables.yaml └── bundle-2 ├── bundle.yaml ├── jenkins.yaml ├── plugins.yaml ├── plugin-catalog.yaml ├── items.yaml ├── rbac.yaml └── variables.yaml

Bundle inheritance with CasC

Bundle inheritance is only supported for controller CasC bundles when they are provisioned by the operations center. The operations center calculates the effective bundle as a result of the inheritance chain and applies it to the controller instance.

You can simplify bundle composition and maintenance by creating a "child" bundle that inherits common configuration elements from a "parent" bundle. In one parent bundle, you can maintain common configuration elements that are automatically inherited by all bundles in the inheritance chain, which eliminates the need to maintain and update individual bundles.

To configure bundle inheritance, you must add a parent property to the child bundle’s bundle.yaml file and specify the parent bundle’s folder name as the value for the parent property.

Child bundles must only contain configuration elements that are unique to that bundle and should not overwrite the parent bundle’s configuration elements. Once the parent bundle and child bundle are configured, the YAML files in the parent and child bundles are processed as follows:

  • Jenkins Configuration as Code files are processed using the rules defined by the Jenkins Configuration as Code plugin.

  • If a plugins.yaml file is present in both the parent and child bundle, the parent and child plugins.yaml files are merged. As different values are possible for the apiVersion field in the bundle.yaml file, refer to the merge process in the bundle inheritance section in casc-plugin-management:index.adoc[Plugin management with CasC] page.

  • If a plugin-catalog.yaml file is present in both the parent and child bundle, the plugin-catalog.yaml in the child bundle is processed and the plugin-catalog.yaml in the parent bundle is ignored.

  • items.yaml files are processed one-by-one. The parent bundle is processed first, followed by the child bundle.

  • rbac.yaml files are processed one-by-one. The parent bundle is processed first, followed by the child bundle.

  • If a variables.yaml file is present in both the parent and child bundles, the parent and child variables.yaml files are both processed. If the same variable name exists in both variables.yaml files, the variable in the child bundle’s variables.yaml file overrides the variable in the parent bundle’s variables.yaml file.

If making a change to a bundle, do not apply the change to all controllers at once. Instead, apply the change to a single controller-specific bundle, verify it works as expected, and then apply the change to all bundles.

Bundle inheritance with multiple branches and tags

A Bundle location is a location added to the operations center that contains CasC bundles. It can be a local file system or a Git repository.

Bundle inheritance is supported for multiple branches and tags in the same bundle location; however, bundle inheritance is not limited to bundles in the same configuration. For example:

  • Parent and child bundles in the same branch from the same location

  • Parent and child bundles in different branches from the same location

  • Parent and child bundles in the same or different branches from different locations pointing to the same repository

  • Parent and child bundles in different repositories in different locations

With branch and tag support, the value of the parent property can be specified in two ways. For example, if you have two branches, main and staging, a child bundle is in the main branch and a parent (global) bundle is in both the main and staging branches. The parent value can be specified as follows:

  • parent: global: This property does not specify a branch. However, because the child bundle is in the main branch, CasC searches for the parent (global) bundle in the same branch.

  • parent: main/global: This property value identifies the branch (main). Therefore, CasC searches for the parent bundle in the main branch.

  • parent: staging/global: This property value identifies the staging branch. Therefore, CasC searches for the parent bundle (global) in the staging branch.

Example bundle inheritance

In this example, there is a parent bundle: bundle-global. There are also two child bundles: bundle-1 and bundle-2. The child bundles use the same jenkins.yaml file and plugins.yaml file as the parent bundle but include unique items in their items.yaml files.

/oc-bundles ├── bundle-global │ ├── bundle.yaml │ ├── jenkins.yaml │ ├── plugins.yaml │ └── items.yaml ├── bundle-1 │ ├── bundle.yaml │ └── items.yaml └── bundle-2 ├── bundle.yaml └── items.yaml

bundle-global example

Within bundle-global, the bundle.yaml file defines:

  • The bundle’s unique id: "bundle-global".

  • The contents of the bundle: a jenkins.yaml file, plugins.yaml file, and items.yaml file.

id: "bundle-global" version: "1" apiVersion: "1" description: "CasC parent bundle with common configuration elements" jcasc: - "jenkins.yaml" plugins: - "plugins.yaml" items: - "items.yaml"

bundle-global includes a jenkins.yaml file that describes the controller:

jenkins: systemMessage: "Controller configured using CloudBees CasC" numExecutors: 0 securityRealm: ldap: configurations: - displayNameAttributeName: "cn" groupMembershipStrategy: fromGroupSearch: filter: "member={0}" groupSearchBase: "ou=Groups" inhibitInferRootDN: false managerDN: "cn=admin,dc=example,dc=org" managerPasswordSecret: ${LDAP_MANAGER_PASSWORD} rootDN: "dc=example,dc=org" server: "ldap://ldap-openldap:389" userSearchBase: "ou=People" disableMailAddressResolver: false groupIdStrategy: "caseInsensitive" userIdStrategy: "caseInsensitive" authorizationStrategy: "cloudBeesRoleBasedAccessControl"

bundle-global includes a plugins.yaml file that contains a list of all plugins to install on the controller:

plugins: # In CloudBees Assurance Program (CAP) - id: "bitbucket-branch-source" - id: "branch-api" - id: "cloudbees-casc-client" - id: "cloudbees-casc-items-api" - id: "cloudbees-casc-items-commons" - id: "cloudbees-casc-items-controller" - id: "cloudbees-template" - id: "cloudbees-workflow-template" - id: "configuration-as-code" - id: "git" - id: "github-branch-source" - id: "infradna-backup" - id: "workflow-multibranch" # Not in CAP (see plugin-catalog.yaml) - id: "manage-permission"

bundle-global includes an items.yaml file that contains the required removeStrategy properties and the root property that defines the root folder path for item creation.

removeStrategy: items: "none" rbac: "sync" root: "/projects"

bundle-1 example

Within bundle-1, the bundle.yaml file defines:

  • The bundle’s unique id: "bundle-1".

  • The parent bundle to inherit from: "bundle-global".

  • The contents of the bundle that are unique to the child bundle. bundle-1 requires additional folders that are not included in the bundle-global parent bundle. Therefore, the items.yaml file must be added, since it is unique to bundle-1.

id: "bundle-1" version: "1" apiVersion: "1" description: "CasC child bundle 1" parent: "bundle-global" items: - "items.yaml"

bundle-1 includes an items.yaml file that contains an additional folder and subfolders that should be created under the /projects folder path specified in bundle-global.

removeStrategy: items: "none" rbac: "sync" items: - kind: "folder" name: "project-alpha" displayName: "Project Alpha" description: "Project Alpha is going to change the world!" items: - kind: "folder" name: "project-alpha-tests" displayName: "Project Alpha Tests" items: - kind: "folder" name: "test-1" - kind: "folder" name: "test-2"

bundle-2 example

Within bundle-2, the bundle.yaml file defines:

  • The bundle’s unique id: "bundle-2".

  • The parent bundle to inherit from: "bundle-global".

  • The contents of the bundle that are unique to the child bundle. bundle-2 requires an additional folder that is not included in the bundle-global parent bundle. Therefore, the items.yaml file must be added, since it is unique to bundle-2.

id: "bundle-2" version: "1" apiVersion: "1" description: "CasC child bundle 2" parent: "bundle-global" items: - "items.yaml"

bundle-2 includes an items.yaml file that contains an additional folder that should be created under the /projects folder path specified in bundle-global.

removeStrategy: items: "none" rbac: "sync" items: - kind: "folder" name: "project-beta" displayName: "Project Beta" description: "Secret project! Only Admins can see this!"