Overview of the Splunk Packaging Toolkit

Welcome to the Splunk Packaging Toolkit! The Packaging Toolkit is a tool for authoring, packaging, and validating a Splunk app in a way that eases up app management, including installation, configuration, and updating.

The Packaging Toolkit provides support for all phases of Splunk app lifecycle management. For Splunk app developers, that means they can focus on building apps without concerning themselves with different deployment topologies or the details of the deployment process. For Splunk Enterprise administrators, it means that they can easily and reliably install and manage Splunk apps across their entire Splunk deployment from a single point.

The Packaging Toolkit, with minimal additional work by developers during design, disambiguates configuration and code, and partitions, or repackages, relevant pieces of an app into deployment packages. Each deployment package can be based on either physical workloads (forwarders, search heads, indexers, etc.) or logical groups of inputs.

This topic contains the following sections:

Key concepts

To understand the Packaging Toolkit and what it does, you must understand the following key concepts:

The app manifest

The Packaging Toolkit relies on an app manifest to keep track of what components go where and what dependencies are required. Even when an app manifest is not provided, the Packaging Toolkit can derive one from .conf files and other Splunk app artifacts.

You are not required to do anything with your current apps to take advantage of partitioning across search heads, indexers, and forwarders, but to take advantage of advanced capabilities around partitioning for different forwarder types and input groups, you must provide logical declarations in the app manifest. If not, the Packaging Toolkit can't break the forwarder types further down. Further, if you don't declare dependencies in the app manifest, the Packaging Toolkit can't do dependency resolution.

When you run the Packaging Toolkit's manifest generation command, it auto-generates a list of physical partitioning details, and it stubs out several additional sections. To enable logical partitioning capabilities and dependency resolution, you must augment the app manifest with additional details.

Partitioning

Splunk Enterprise allows you to put any app or add-on you'd like onto any deployment node, even if it's not relevant to or intended for that type of node. For example, modular inputs have no reason to run on a search head, but if components related to modular inputs exist in your Splunk app and you distribute the app to a search head, those modular input components will run on that search head. This is unnecessary, and can lead to problems and potential performance issues in a complex deployment.

The Packaging Toolkit's main capability is partitioning. Partitioning is the act of taking a Splunk app's source package, examining it, and splitting it into a minimum of three deployment packages. Each deployment package contains only the information, configuration, and corresponding code that is relevant to the type of deployment node for which it is intended.

The following diagram illustrates this concept. In it, the Packaging Toolkit generates three deployment packages: one for search heads, one for indexers, and one for forwarders.

Diagram illustrating Packaging Toolkit partitioning: Source package on the left leads to the Packaging Toolkit, which splits it into three deployment packages, each intended for a different deployment node.

This functionality is available in the Packaging Toolkit out of the box, with no additional development necessary for your Splunk app. All existing Splunk apps can be partitioned into these three workloads automatically.

This is partitioning across physical boundaries. Each deployment node is its own workload. The Packaging Toolkit can also partition across logical boundaries for forwarders. Partitioning among logical groups must be done by developers at design time. Later, at deployment time, admins can map logical groups to collections of server classes or nodes.

For example, you might want to have a dedicated deployment package not just for all forwarders, but one that contains special handling for a group of forwarders that deal with Microsoft Exchange data. If a developer has the unique logic and code that apply to that logical group and wants to package it, the Packaging Toolkit enables the developer to declare those logical groupings. It will then, when partitioning, respect those declarations. At install time, admins can either map the logical groups to nodes of server classes or ignore them altogether and collapse them all into one.

Input groups

An input group specifies a named group of data inputs as defined in the inputs.conf file. Each group typically targets a specific forwarding environment. Input groups can be selectively deployed to specific server classes. For example, you could define an input group that targets AD domain servers on specific versions of Windows.

You define input groups in the app.manifest file. To learn more about defining input groups, see the app.manifest schema topic. In particular, see the schema members that begin with inputGroups. You can define the following input group attributes, among others, from within the app.manifest file:

  • Required dependencies
  • List of included data inputs
  • Defined stanzas in inputs.conf
  • Descriptive information

By setting the appropriate app.manifest attributes, developers can enable the Packaging Toolkit to seamlessly integrate an app with the input groups of its dependencies, and Splunk admins can select input groups for deployment without needing to know about the underlying app dependencies and their input groups.

Packaging Toolkit workflows

This section contains descriptions of typical Packaging Toolkit workflows. The first is for developers, and is usually followed by the admin workflow.

Developer workflow

To try out the Packaging Toolkit, you'll want to do the following:

  1. Download and install the Packaging Toolkit.

  2. If your app includes custom .conf files, add corresponding placement rules to the conf.spec files. See Creating placement rules for custom .conf files later on this page.

  3. Generate an app manifest for your app using the generate-manifest command. The Packaging Toolkit parses the app's .conf files to validate the app configuration. The default generated manifest has basic information already filled out, such as the app name, author name, description, and so on.

  4. Augment the required manifest sections, such as [supportedDeployments]. See the full list of required app manifest sections later on this page.

  5. Augment the rest of the manifest as needed, in particular the [dependencies] and [inputGroups] sections. See app manifest augmentation recommendations later on this page.

  6. With the app manifest at the root of the app folder, validate the app source using the validate command.

  7. Finally, package the app source using the package command. Specify a repository if you are including static dependencies with your main app.

The Packaging Toolkit looks at the app manifest and performs dependency resolution. It makes sure that any of the packages that you've defined as dependencies don't conflict with each other. The output of the package operation is the app, along with its dependencies if you opted to package them with the app. The package's file name is in the form <group_name>-<app_name>-<version>.tar.gz. For <version>, the Packaging Toolkit uses Semantic Versioning (semver) notation. Note that this is simply the name of the package. The name of the app has not changed.

This completes the Packaging Toolkit developer workflow. You now have a package with an app manifest defined with dependencies and input groups. You can now hand the package off to a Splunk admin, who does partitioning and input group mapping.

Admin workflow

Though a user interface is planned for the admin workflow of the Packaging Toolkit, admins can also use the CLI, which is available now.

  1. Use the partition command to partition the app into deployment packages. If you partition an app without any input group mappings, you generate the three default deployment packages. You can also specify input group mappings on the command line.

  2. Resolve any dependency conflicts. The packaging toolkit checks the dependencies specified in the app that you are partitioning against any installed apps, and might perform one of the following resolutions.

    • Requests authorization if the app that you are partitioning requires any installed apps to be upgraded or downgraded.
    • Fails if the app that you are partitioning or its dependencies are incompatible with any installed apps.
  3. If the packaging toolkit does not find any conflicts, then it generates the deployment packages according to the manifest without requesting authorization. You can now deploy the resulting deployment packages.

Creating placement rules for custom .conf files

If you create a custom .conf file, then you need to create placement rules. Placement rules tell the Packaging Toolkit how to partition the .conf files, or stanzas within the .conf files, into deployment packages. Add placement rules such as @placement indexer, @placement forwarder, or @placement search-head to the corresponding conf.spec file.

You can also combine placement rules. For example, use @placement search-head, indexer to partition the .conf file to both the search head and indexer deployment packages.

Base your placement rules on the following example from props.conf.spec.

@placement forwarder

CHARSET = <string>
* This setting applies at input time, when data is first read by Splunk.
  
@placement indexer
  
LINE_BREAKER = <regular expression>
* Specifies a regex that determines how the raw text stream is broken into initial events, before line merging takes place. (See the SHOULD_LINEMERGE attribute, below)
TRUNCATE = <non-negative integer>
* Changes the default maximum line length (in bytes).
TRANSFORMS-<class> = <transform_stanza_name>, <transform_stanza_name2>,...
* Used for creating indexed fields (index-time field extractions).

Required app manifest sections

In the Splunk Packaging Toolkit version 1.0.0 and later only, the app manifest contains additional required sections. Previous versions do not require these sections to be added.

Supported deployments

This section defines what Splunk deployments your app is supported on. As a required section, at least one Splunk deployment type must be present:

Deployment Description
* App is supported on all the following Splunk deployment types.
_standalone App is supported on standalone Splunk deployments (single Splunk instance).
_distributed App is supported on distributed Splunk deployments (Index Clustering with single Search Head).
_search_head_clustering App is supported on distributed Splunk deployments (Index Clustering with Search Head Clustering).

The * notation indicates all Splunk deployment types are supported.

By default, this section is populated with both _standalone and _distributed values:

{
    ...
    "supportedDeployments": ["_standalone", "_distributed"]
}

Support for Search Head Clustering is not assumed, and is therefore not included by default. If you know your app works in Search Head Clustering, you can add that value to the manifest (or use the * notation).

Optional app manifest augmentations

Consider augmenting the following sections within the app manifest to better define your app:

Dependencies

This section defines what other apps your app requires, indicated by <app-group>-<app-name>. You must specify a specific version number or range of versions that your app will accept using the version field. Specifying "*" indicates any version is accepted. The Packaging Toolkit recognizes Semantic Versioning (semver notation) to indicate version numbers and ranges.

For example, if you require any version of the app linux_utils from 1.0.0 onwards as a dependency, then add the following section to the app.manifest file:

{
    ...
    "dependencies": {
        "linux_utils": {
            "version": ">=1.0.0"
        }
    }
}

The Packaging Toolkit provides two options for resolving dependencies when you define them in the app manifest:

  • You can include the dependent app packages statically within your app.
  • You can declare the dependent app packages dynamically to be resolved either by the CLI referencing the local repository during validation/packaging/partitioning, or by Splunk referencing Splunkbase during installation.
Note: The Splunk Packaging Toolkit cannot yet resolve dynamically declared dependencies by referencing Splunkbase, and therefore the dependent apps must live in the local repository.

To include the dependent app packages within your app, specify them in the app manifest using package field. For example, if you want to include version 1.0.0 of linux_utils statically, then add the following section to the app.manifest file:

{
    ...
    "dependencies": {
        "linux_utils": {
            "version": ">=1.0.0",
            "package": "linux_utils-1.0.0.tgz"
        }
    }
}

Starting in version 1.0.0, the Packaging Toolkit provides a new option for resolving dependencies optionally. An optional dependency will not block the packaging and installation if the optional dependency app is missing. If the optional dependency is supplied, it must satisfy the version requirements.

{
    ...
    "dependencies": {
        "linux_utils": {
            "version": ">=1.0.0",
            "optional": true
        }
    }
}

Starting in version 1.0.0, the Packaging Toolkit provides a new option for targeting dependencies to a specific OS platform only. This is useful when you have multiple dependencies that differ only by OS support. Supported OS platforms include: _mac, _windows, _linux_x86, and _linux_x86_64.

For example, the Splunk Machine Learning Toolkit has a dependency on the Python for Scientific Computing Add-on, which is designed for specific OS platforms:

{
    ...
    "dependencies": {
        "Splunk_SA_Scientific_Python_linux_x86": {
            "version": "1.2",
            "targetOS": ["_linux_x86"]
          ]
        },
        "Splunk_SA_Scientific_Python_linux_x86_64": {
            "version": "1.2",
            "targetOS": ["_linux_x86_64"]
        },
        "Splunk_SA_Scientific_Python_windows_x86_64": {
            "version": "1.2",
            "targetOS": ["_windows"]
        },
        "Splunk_SA_Scientific_Python_darwin_x86_64": {
            "version": "1.2",
            "targetOS": ["_mac"]
        }
    }
}

During packaging, these dependencies are included in a hidden .dependencies folder. The Packaging Toolkit uses the .dependencies folder in all commands except for slim generate-manifest. See the following example directory structure for the location of the hidden .dependencies folder:

|-- <app_id>-<version>.tar.gz
|   |-- <app_source>
|   |-- .dependencies
|       |-- <dependency_1>-<version>.tar.gz
|       |-- <dependency_2>-<version>.tar.gz

You only need to know and declare top-level dependencies. That is, if your dependencies have their own dependencies, such as a utility or another app, the Packaging Toolkit will find these "nested" dependencies and validate their version numbers.

Incompatible apps

This section allows apps developers to define specific apps (or app versions) that will not work with their app on the same system. By defining apps in this section, Splunk can prevent installation of either your app or the incompatible app. The version field can be either a specific version, and version range, or * to indicate app versions of an app.

{
    ...
    "incompatibleApps": {
        "conflicting_app": "~1.0.0",
        "another_app": "*"
    }
}

Input groups

Input groups are logical groupings of inputs either directly from your app, or bubbled up from your dependencies. You may want to create input groups if you have specific inputs that must be located on the same server class machine, for example platform specific characteristics.

In addition to inputs defined in your app, you can define which input groups in a dependent app that you want to bubble up into a top-level input group. Use the "*" notation to indicate you want all input groups to bubble up.

For example, if you have platform specific inputs you may want to create platform specific input groups. The following example app, myapp, has a dependency on linux_utils and contains different collection inputs depending on the platform.

{
    ...
    "inputGroups": {
        "myapp_linux": {
            "inputs": ["input://linux_collection"],
            "requires": {
                "linux_utilities": "*"
            },
        },
        "myapp_windows": {
            "inputs": ["input://windows_collection"]
        }
    }
}

Tasks

By default, the Packaging Toolkit partitions all stanzas defined in the inputs.conf file to the forwarder deployment package. However, you may have management or scheduled tasks defined that need to be partitioned to the search head deployment package instead. You can indicate these stanzas in the app manifest file.

For example, if you define [input://task_id] in your inputs.conf file, and this should be run on the search head, then add the following section to the app.manifest file:

{
    ...
    "tasks": ["input://task_id"]
}

Target workloads

This section is required when using the Splunk Packaging Toolkit version 1.0.0 and later only. It defines what Splunk workloads your app should be installed on, and what deployment packages are generated at partition time. By default, the Packaging Toolkit will partition an app into deployment packages targeting all Splunk workloads:

Workload Description
* App should be partitioned to all Splunk workloads.
_search_heads App should be partitioned to Splunk search heads.
_indexers App should be partitioned to Splunk indexers.
_forwarders App should be partitioned to Splunk forwarders.

However, in some cases it may not be desired that all deployment packages are generated. For example, if you have an app that simply contains dashboards, there is no reason for it to be installed on indexers or forwarders. In this case, augment the app.manifest file:

{
    ...
    "targetWorkloads": ["_search_heads"]
}