# ConfigurationLabel and TenantLabel Patterns for User-Level and Tenant-Level Configuration Management in Linkis

> Understand Linkis ConfigurationLabel and TenantLabel patterns for user and tenant configuration. Learn about hierarchical management and wildcard fallback.

- Repository: [The Apache Software Foundation/linkis](https://github.com/apache/linkis)
- Tags: architecture
- Published: 2026-02-25

---

**Linkis implements hierarchical configuration management through label-based scoping, where `UserCreatorLabel` stores user-specific settings in `<user>-<creator>` format and `TenantLabel` stores tenant-wide defaults, with automatic wildcard fallback mechanisms when exact matches are unavailable.**

Apache Linkis employs a sophisticated label-driven configuration system that enables fine-grained control over computing resources and execution parameters. The platform distinguishes between **user-level** settings tied to individual sessions and **tenant-level** defaults that apply across organizational boundaries. Understanding the `ConfigurationLabel` and `TenantLabel` patterns is essential for administrators managing multi-tenant clusters and for configuring how the system resolves configuration priorities.

## User-Level Configuration with UserCreatorLabel

The `UserCreatorLabel` (defined by the key constant `LabelKeyConstant.USER_CREATOR_TYPE_KEY`) manages configurations specific to individual users and their creation contexts, such as IDE sessions or notebook applications.

### Pattern Structure and Wildcard Syntax

The label value follows the strict pattern `<user>-<creator>`, producing values like `alice-IDE` or `bob-Notebook`. When querying configurations, Linkis first attempts an exact match for the specific user-creator pair. If no specific configuration exists, the system falls back to wildcard patterns using the asterisk (`*`) character.

The helper method `LabelParameterParser.changeUserToDefault` in [`linkis-public-enhancements/linkis-configuration/src/main/scala/org/apache/linkis/configuration/util/LabelParameterParser.scala`](https://github.com/apache/linkis/blob/main/linkis-public-enhancements/linkis-configuration/src/main/scala/org/apache/linkis/configuration/util/LabelParameterParser.scala) handles this transformation. This utility replaces concrete user and creator values with wildcards to retrieve default configurations that apply to any user or creator within a given engine context.

### Implementation in ConfigurationService

The `ConfigurationService` class, located in [`linkis-public-enhancements/linkis-configuration/src/main/scala/org/apache/linkis/configuration/service/ConfigurationService.scala`](https://github.com/apache/linkis/blob/main/linkis-public-enhancements/linkis-configuration/src/main/scala/org/apache/linkis/configuration/service/ConfigurationService.scala), orchestrates user-level configuration lookups through the `generateCombinedLabel` method. This method constructs a `CombinedLabel` via `CombinedLabelBuilder`, creating a composite lookup key that incorporates the user identity, creator type, engine type, and version.

```scala
import org.apache.linkis.manager.label.builder.factory.LabelBuilderFactoryContext
import org.apache.linkis.manager.label.constant.LabelKeyConstant
import org.apache.linkis.manager.label.entity.engine.{EngineTypeLabel, UserCreatorLabel}
import org.apache.linkis.manager.label.builder.CombinedLabelBuilder

// Build a config label for user "bob", creator "IDE", Spark 2.4
val labelFactory = LabelBuilderFactoryContext.getLabelBuilderFactory
val userCreator = labelFactory.createLabel[UserCreatorLabel](
  LabelKeyConstant.USER_CREATOR_TYPE_KEY
)
userCreator.setUser("bob")
userCreator.setCreator("IDE")

val engineType = labelFactory.createLabel[EngineTypeLabel](
  LabelKeyConstant.ENGINE_TYPE_KEY
)
engineType.setEngineType("spark")
engineType.setVersion("2.4")

val labelList = java.util.Arrays.asList(userCreator, engineType)
val combined = new CombinedLabelBuilder().build("", labelList)
// DAO queries ConfigKeyValue rows using this combined label

```

## Tenant-Level Configuration with TenantLabel

The `TenantLabel` (key: `tenant` via `LabelKeyConstant.TENANT_KEY`) provides organization-wide configuration defaults that apply to all users within a specific tenant, such as `finance` or `engineering`.

### Automatic Label Injection

When a job request enters the system without explicit tenant information, the `TenantLabelSetUtils.checkTenantLabel` method in [`linkis-computation-governance/linkis-entrance/src/main/scala/org/apache/linkis/entrance/interceptor/impl/TenantLabelSetUtils.scala`](https://github.com/apache/linkis/blob/main/linkis-computation-governance/linkis-entrance/src/main/scala/org/apache/linkis/entrance/interceptor/impl/TenantLabelSetUtils.scala) intercepts the request. This utility verifies the presence of a tenant label and, if missing, queries the **TenantCache** to retrieve the tenant association for the requesting user.

```scala
import org.apache.linkis.manager.label.builder.factory.LabelBuilderFactoryContext
import org.apache.linkis.manager.label.constant.LabelKeyConstant
import org.apache.linkis.manager.label.entity.TenantLabel

def ensureTenantLabel(labels: java.util.List[Label[_]], tenantFromCache: String): Unit = {
  if (!labels.stream().anyMatch(_.getLabelKey == LabelKeyConstant.TENANT_KEY)) {
    val tenantLabel = LabelBuilderFactoryContext.getLabelBuilderFactory
      .createLabel[TenantLabel](LabelKeyConstant.TENANT_KEY)
    tenantLabel.setTenant(tenantFromCache)  // e.g., "finance"
    labels.add(tenantLabel)
  }
}

```

### Tenant Cache Integration

The tenant name is fetched from a cache populated by manager services. If no specific tenant is configured for the user, the system defaults to the wildcard `*`, allowing generic tenant-agnostic configurations to apply across the cluster.

## Combined Labels and Hierarchical Resolution

For complete configuration resolution, Linkis combines multiple labels into a single `CombinedLabel` that serves as the database lookup key. The resolution hierarchy follows this priority order:

1.  **Exact User + Tenant**: Specific user, creator, engine, version, and tenant
2.  **User Default**: Wildcard user and creator (`*-*`) with specific engine and tenant
3.  **Tenant Default**: Specific tenant with wildcard user/creator, or global wildcard (`*`)

The `CombinedLabelBuilder` constructs these composite keys, enabling the configuration DAO to perform tiered lookups. The `ConfigurationService.getConfigsByLabelList` method automates this fallback chain by invoking `LabelParameterParser.changeUserToDefault` when initial queries return no results.

```scala
val configService = new ConfigurationService()
val userLabelList = LabelEntityParser.generateUserCreatorEngineTypeLabelList(
  "alice", "IDE", "spark", "2.4"
)

// Queries exact label first, then falls back to "*-*" defaults
val (userConf, defaultConf) = configService.getConfigsByLabelList(
  userLabelList, 
  useDefaultConfig = true, 
  language = "en"
)

```

## Key Source Files and Their Roles

| File Path | Role in Configuration Management |
|-----------|----------------------------------|
| [`linkis-computation-governance/linkis-manager/linkis-label-common/src/main/java/org/apache/linkis/manager/label/constant/LabelKeyConstant.java`](https://github.com/apache/linkis/blob/main/linkis-computation-governance/linkis-manager/linkis-label-common/src/main/java/org/apache/linkis/manager/label/constant/LabelKeyConstant.java) | Defines label keys including `USER_CREATOR_TYPE_KEY` and `TENANT_KEY` |
| [`linkis-public-enhancements/linkis-configuration/src/main/scala/org/apache/linkis/configuration/util/LabelParameterParser.scala`](https://github.com/apache/linkis/blob/main/linkis-public-enhancements/linkis-configuration/src/main/scala/org/apache/linkis/configuration/util/LabelParameterParser.scala) | Provides `changeUserToDefault` for wildcard transformation and label normalization |
| [`linkis-public-enhancements/linkis-configuration/src/main/scala/org/apache/linkis/configuration/service/ConfigurationService.scala`](https://github.com/apache/linkis/blob/main/linkis-public-enhancements/linkis-configuration/src/main/scala/org/apache/linkis/configuration/service/ConfigurationService.scala) | Generates combined labels via `generateCombinedLabel` and manages configuration queries with fallback logic |
| [`linkis-computation-governance/linkis-entrance/src/main/scala/org/apache/linkis/entrance/interceptor/impl/TenantLabelSetUtils.scala`](https://github.com/apache/linkis/blob/main/linkis-computation-governance/linkis-entrance/src/main/scala/org/apache/linkis/entrance/interceptor/impl/TenantLabelSetUtils.scala) | Implements `checkTenantLabel` to automatically inject tenant labels from cache |
| [`linkis-orchestrator/linkis-orchestrator-core/src/main/scala/org/apache/linkis/orchestrator/plans/ast/StartupParams.scala`](https://github.com/apache/linkis/blob/main/linkis-orchestrator/linkis-orchestrator-core/src/main/scala/org/apache/linkis/orchestrator/plans/ast/StartupParams.scala) | Exposes `getConfigurationLabels` for downstream components to retrieve built labels |

## Summary

- **UserCreatorLabel** uses the pattern `<user>-<creator>` (e.g., `alice-IDE`) to scope configurations to specific user sessions, with `LabelParameterParser.changeUserToDefault` enabling wildcard (`*-*`) fallbacks.
- **TenantLabel** stores tenant names (e.g., `finance`) and is automatically injected by `TenantLabelSetUtils.checkTenantLabel` when missing from job requests.
- **CombinedLabel** aggregates multiple label types into a single lookup key used by the configuration DAO, supporting hierarchical resolution from specific to default settings.
- The **ConfigurationService** orchestrates queries across both user and tenant scopes, ensuring tenant-level defaults apply unless overridden by user-specific values.

## Frequently Asked Questions

### What is the exact format of a UserCreatorLabel in Linkis?

The `UserCreatorLabel` stores values in the format `<user>-<creator>`, such as `alice-IDE` or `bob-Notebook`, defined by the constant `LabelKeyConstant.USER_CREATOR_TYPE_KEY` in [`LabelKeyConstant.java`](https://github.com/apache/linkis/blob/main/LabelKeyConstant.java). Wildcards (`*`) can substitute for either component to denote default configurations applicable to any user or creator.

### How does Linkis handle missing tenant labels in job requests?

When a job request lacks a tenant label, the `TenantLabelSetUtils.checkTenantLabel` method in the entrance interceptor automatically queries the **TenantCache** to retrieve the user's associated tenant. It then constructs a `TenantLabel` and injects it into the request labels, defaulting to `*` if no tenant mapping exists.

### Can user-level configurations override tenant-level defaults?

Yes, the configuration resolution hierarchy prioritizes exact user-creator matches before falling back to tenant-level wildcards. The `ConfigurationService` queries the specific combined label first, and only if no value is found does it invoke `LabelParameterParser.changeUserToDefault` to check tenant-wide or global defaults.

### Where is the wildcard fallback logic implemented for user configurations?

The wildcard transformation logic resides in `LabelParameterParser.changeUserToDefault` within [`linkis-public-enhancements/linkis-configuration/src/main/scala/org/apache/linkis/configuration/util/LabelParameterParser.scala`](https://github.com/apache/linkis/blob/main/linkis-public-enhancements/linkis-configuration/src/main/scala/org/apache/linkis/configuration/util/LabelParameterParser.scala). This method replaces concrete user and creator strings with `*` characters to generate default label patterns for fallback queries.