For article #45967: Rollout rings with Fleet labels. Adds three drop-in label YAML files under docs/solutions/all/labels/: rollout-rings.labels.yml — five cumulative dynamic labels (1%, 5%, 25%, 75%, 100%) for gradual software rollouts via labels_include_any. Each ring is a superset of the previous. rollout-waves.labels.yml — five disjoint dynamic labels covering the same percentage breakpoints, for A/B experiments and per-wave reporting. pinned-canaries.labels.yml — manual label for pinning specific hosts (dev Macs, QA machines) into the first wave regardless of their natural UUID shard. All three use the same deterministic UUID-based shard expression (positions 10 and 25, avoiding RFC 4122's fixed version/variant digits at positions 15 and 20) so a host's ring assignment never changes across reboots or agent reinstalls. New folder docs/solutions/all/labels/ follows the existing pattern of docs/solutions/all/policies/ and docs/solutions/all/queries/. The companion article is in draft and will follow in a separate PR; it references these files via https://github.com/fleetdm/fleet/blob/main/docs/solutions/all/labels/... URLs. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Documentation** * Added comprehensive labeling solutions for managing staged rollouts: manual pinned canaries for selecting priority hosts, cumulative rollout rings covering multiple deployment phases (1%, 5%, 25%, 75%, 100%), and partitioned rollout waves for balanced phased distribution strategies. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45971?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
72 lines
2.4 KiB
YAML
72 lines
2.4 KiB
YAML
# Rollout waves. Disjoint model.
|
|
# Reference from default.yml with:
|
|
# labels:
|
|
# - path: ./labels/rollout-waves.labels.yml
|
|
#
|
|
# Same shard expression as rollout-rings.labels.yml:
|
|
# Shard = ((hex@pos10 nibble) * 16) + (hex@pos25 nibble) → 0-255.
|
|
# Each wave is a range, so every host belongs to exactly one wave.
|
|
# Use this when you need clean per-wave metrics or A/B experiments.
|
|
|
|
- name: Wave 1 - Canary (0-1%)
|
|
description: "Disjoint. Hosts with shard < 3."
|
|
label_membership_type: dynamic
|
|
query: |
|
|
SELECT 1 FROM system_info
|
|
WHERE (
|
|
(instr('0123456789abcdef', lower(substr(uuid, 10, 1))) - 1) * 16
|
|
+ (instr('0123456789abcdef', lower(substr(uuid, 25, 1))) - 1)
|
|
) < 3;
|
|
|
|
- name: Wave 2 - Early (1-5%)
|
|
description: "Disjoint. ~4% slice. Excludes Wave 1."
|
|
label_membership_type: dynamic
|
|
query: |
|
|
SELECT 1 FROM system_info
|
|
WHERE (
|
|
(instr('0123456789abcdef', lower(substr(uuid, 10, 1))) - 1) * 16
|
|
+ (instr('0123456789abcdef', lower(substr(uuid, 25, 1))) - 1)
|
|
) >= 3
|
|
AND (
|
|
(instr('0123456789abcdef', lower(substr(uuid, 10, 1))) - 1) * 16
|
|
+ (instr('0123456789abcdef', lower(substr(uuid, 25, 1))) - 1)
|
|
) < 13;
|
|
|
|
- name: Wave 3 - Pilot (5-25%)
|
|
description: "Disjoint. 20% slice."
|
|
label_membership_type: dynamic
|
|
query: |
|
|
SELECT 1 FROM system_info
|
|
WHERE (
|
|
(instr('0123456789abcdef', lower(substr(uuid, 10, 1))) - 1) * 16
|
|
+ (instr('0123456789abcdef', lower(substr(uuid, 25, 1))) - 1)
|
|
) >= 13
|
|
AND (
|
|
(instr('0123456789abcdef', lower(substr(uuid, 10, 1))) - 1) * 16
|
|
+ (instr('0123456789abcdef', lower(substr(uuid, 25, 1))) - 1)
|
|
) < 64;
|
|
|
|
- name: Wave 4 - Broad (25-75%)
|
|
description: "Disjoint. 50% slice."
|
|
label_membership_type: dynamic
|
|
query: |
|
|
SELECT 1 FROM system_info
|
|
WHERE (
|
|
(instr('0123456789abcdef', lower(substr(uuid, 10, 1))) - 1) * 16
|
|
+ (instr('0123456789abcdef', lower(substr(uuid, 25, 1))) - 1)
|
|
) >= 64
|
|
AND (
|
|
(instr('0123456789abcdef', lower(substr(uuid, 10, 1))) - 1) * 16
|
|
+ (instr('0123456789abcdef', lower(substr(uuid, 25, 1))) - 1)
|
|
) < 192;
|
|
|
|
- name: Wave 5 - Tail (75-100%)
|
|
description: "Disjoint. Final 25% slice."
|
|
label_membership_type: dynamic
|
|
query: |
|
|
SELECT 1 FROM system_info
|
|
WHERE (
|
|
(instr('0123456789abcdef', lower(substr(uuid, 10, 1))) - 1) * 16
|
|
+ (instr('0123456789abcdef', lower(substr(uuid, 25, 1))) - 1)
|
|
) >= 192;
|