ConfigurationLabel and TenantLabel Patterns for User-Level and Tenant-Level Configuration Management in Linkis
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 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, 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.
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 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.
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:
- Exact User + Tenant: Specific user, creator, engine, version, and tenant
- User Default: Wildcard user and creator (
*-*) with specific engine and tenant - 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.
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
Summary
- UserCreatorLabel uses the pattern
<user>-<creator>(e.g.,alice-IDE) to scope configurations to specific user sessions, withLabelParameterParser.changeUserToDefaultenabling wildcard (*-*) fallbacks. - TenantLabel stores tenant names (e.g.,
finance) and is automatically injected byTenantLabelSetUtils.checkTenantLabelwhen 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. 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. This method replaces concrete user and creator strings with * characters to generate default label patterns for fallback queries.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →