Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,14 @@ symlink-binaries:
binlocal="{{ justfile_directory() }}/.local/bin"
mkdir -p $binlocal

# Create symlinks only if they don't already exist
# Create or update symlinks, skipping binaries in our own .local/bin to avoid circular references
for binary in aws az pulumi; do
if [ ! -e "$binlocal/$binary" ]; then
ln -sf "$(which $binary)" "$binlocal/$binary"
target="$(PATH="${PATH//$binlocal:/}" which "$binary" 2>/dev/null)"
if [ -z "$target" ]; then
printf 'WARNING: %s not found in PATH (excluding %s), skipping\n' "$binary" "$binlocal" >&2
continue
fi
ln -sf "$target" "$binlocal/$binary"
done

install-thumbprint:
Expand Down Expand Up @@ -195,6 +198,7 @@ test-e2e URL="":
cli:
mkdir -p .local/bin
goreleaser build --single-target --snapshot --clean -o .local/bin/ptd
@codesign --force --sign - .local/bin/ptd 2>/dev/null

#############################################################################
# Check targets
Expand Down
32 changes: 32 additions & 0 deletions docs/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,38 @@ spec:
positronConfig:
sessionTimeoutKillHours: 4

# Session label injection — presence of this block enables the feature.
# The controller reads a field from each session pod, matches entries against
# searchRegex, and writes one numbered label per match (user-group-1, user-group-2, …).
# See docs/team-operator/README.md for full details.
sessionLabels:
# Dot-path into the pod spec identifying the field with the comma-separated group list.
# Supports array index notation. Default: "spec.containers[0].args"
sourceField: "spec.containers[0].args"

# Sub-key used to extract the value from the resolved field:
# args slice → flag name whose next element is the value
# map field → map key to look up (e.g. annotation or label key)
# string field → ignored; field value used directly
# Default: "--container-user-groups"
sourceKey: "--container-user-groups"

# Regex applied to each comma-separated entry. Only matching entries become labels.
# Default: "_entra_[^ ,]+"
searchRegex: "_entra_[^ ,]+"

# Prefix stripped from the start of each matched entry before it becomes the label value.
# Default: "_"
trimPrefix: "_"

# Prefix for generated label keys. Default "user-group-" produces user-group-1, user-group-2, …
labelKeyPrefix: "user-group-"

# When true, forces re-labeling of all existing session pods for this site.
# Use after changing searchRegex or trimPrefix to update already-processed pods.
# Set back to false (or omit) once done. Default: false
reprocess: false

# Posit Connect (Publishing)
connect:
replicas: 2
Expand Down
4 changes: 4 additions & 0 deletions docs/team-operator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ kubectl edit site main -n posit-team
kubectl logs -n posit-team deploy/team-operator
```

## Session Label Injection

See [posit-dev/team-operator#123](https://github.com/posit-dev/team-operator/pull/123) for full details. Configuration schema is in [CONFIGURATION.md](../CONFIGURATION.md).

## Related Documentation

- [Site Management Guide](../guides/product-team-site-management.md) - For product teams
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -701,7 +701,7 @@ def _define_kube_state_metrics(self, release: str, version: str):
"valuesContent": yaml.dump(
{
"metricLabelsAllowlist": [
"pods=[launcher-instance-id]",
"pods=[launcher-instance-id,user-group-*]",
]
}
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,7 @@ def _define_kube_state_metrics(self, release: str, version: str):
"valuesContent": yaml.dump(
{
"metricLabelsAllowlist": [
"pods=[launcher-instance-id]",
"pods=[launcher-instance-id,user-group-*]",
]
}
),
Expand Down
17 changes: 17 additions & 0 deletions python-pulumi/src/ptd/pulumi_resources/team_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import pulumi
import pulumi_kubernetes as kubernetes
import yaml

import ptd
import ptd.workload
Expand Down Expand Up @@ -75,6 +76,17 @@ def _define_posit_team_namespace(self):
),
)

def _any_site_has_session_labels(self) -> bool:
"""Return True if any site.yaml in this workload has workbench.sessionLabels set."""
for site_name in self.workload.cfg.sites:
site_yaml_path = self.workload.site_yaml(site_name)
if not site_yaml_path.exists():
continue
site_dict = yaml.safe_load(site_yaml_path.read_text())
if site_dict.get("spec", {}).get("workbench", {}).get("sessionLabels"):
return True
return False

def _define_helm_release(self):
# Parse self.image (from _define_image) into repository and tag
# Format is either "repo@sha256:digest" or "repo:tag"
Expand Down Expand Up @@ -134,6 +146,11 @@ def _define_helm_release(self):
"enable": not self.cluster_cfg.team_operator_skip_crds,
"keep": True,
},
# Enable the session group label controller only if at least one site
# has workbench.sessionLabels configured in its site.yaml.
"sessionGroupLabels": {
"enable": self._any_site_has_session_labels(),
},
}

# OCI Helm chart from public repository
Expand Down
Loading