> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ctrlplane.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Selectors

> Powerful filtering system for targeting resources, environments, and deployments

**Selectors** are Ctrlplane's powerful filtering system for targeting resources, environments, and deployments. They allow dynamic, rules-based matching instead of static assignments.

## Why Selectors?

Traditional deployment tools require manually assigning resources to environments. Ctrlplane uses selectors for dynamic matching:

### Without Selectors (Traditional)

```
Production Environment:
  ├─ Manually add: cluster-1
  ├─ Manually add: cluster-2
  └─ Manually add: cluster-3

New cluster added? Manually add it to production.
```

### With Selectors (Ctrlplane)

```
Production Environment:
  └─ Selector: metadata.environment == "production"

New cluster with metadata.environment = "production"?
Automatically included in production!
```

## Selector Types

Ctrlplane supports several types of selectors:

1. **Metadata Selector** - Match on resource metadata
2. **Kind Selector** - Match on resource kind
3. **Identifier Selector** - Match on resource identifier
4. **Name Selector** - Match on resource/environment name
5. **CEL Selector** - Complex expressions using CEL (Common Expression Language)
6. **Composite Selectors** - Combine selectors with AND/OR logic

## Metadata Selector

Match resources based on metadata key-value pairs using CEL expressions.

### Simple Equality

```yaml theme={null}
resourceSelector: resource.metadata["environment"] == "production"
```

Matches resources where `metadata.environment === "production"`.

### Supported Operators

#### equals

Exact match:

```yaml theme={null}
resourceSelector: resource.metadata["region"] == "us-east-1"
```

#### not\_equals

Does not match:

```yaml theme={null}
resourceSelector: resource.metadata["deprecated"] != "true"
```

#### contains

Value contains substring:

```yaml theme={null}
resourceSelector: resource.identifier.contains("prod")
```

Matches: `prod-cluster-1`, `k8s-prod`, `production-server`.

#### matches (Regex)

Regular expression match:

```yaml theme={null}
resourceSelector: resource.identifier.matches("^prod-.*-[0-9]+$")
```

Matches: `prod-cluster-1`, `prod-server-42`.

#### exists

Key exists with any value:

```yaml theme={null}
resourceSelector: has(resource.metadata["team"])
```

Matches any resource with a `team` metadata key.

#### not\_exists

Key does not exist:

```yaml theme={null}
resourceSelector: "!has(resource.metadata[\"deprecated\"])"
```

#### in

Value is in a list:

```yaml theme={null}
resourceSelector: resource.metadata["region"] in ["us-east-1", "us-east-2", "us-west-1"]
```

#### not\_in

Value is not in a list:

```yaml theme={null}
resourceSelector: "!(resource.metadata[\"status\"] in [\"deprecated\", \"decommissioned\"])"
```

## Kind Selector

Match resources by their `kind` field.

```yaml theme={null}
resourceSelector: resource.kind == "KubernetesCluster"
```

**Common Use Cases**:

* Kubernetes-only deployments: `resource.kind == "KubernetesCluster"`
* VM-only deployments: `resource.kind == "VirtualMachine"`
* Exclude certain kinds: `resource.kind != "DeprecatedResource"`

## Identifier Selector

Match resources by their identifier.

```yaml theme={null}
resourceSelector: resource.identifier.contains("prod")
```

**Use Cases**:

* Match specific naming patterns
* Filter by identifier prefix/suffix
* Regex matching on identifiers

## Name Selector

Match by the resource or environment name field.

```yaml theme={null}
# In policy selectors
environments: environment.name == "Production"
```

**Use Cases**:

* Policy selectors targeting specific environments
* Matching resources by name patterns

## Composite Selectors (AND/OR)

Combine multiple conditions with boolean logic using CEL operators.

### AND Logic

All conditions must match:

```yaml theme={null}
resourceSelector: >-
  resource.metadata["environment"] == "production" &&
  resource.metadata["region"] == "us-east-1"
```

Matches: Resources with BOTH `environment=production` AND `region=us-east-1`.

### OR Logic

Any condition can match:

```yaml theme={null}
resourceSelector: >-
  resource.metadata["region"] == "us-east-1" ||
  resource.metadata["region"] == "us-west-2"
```

Matches: Resources in EITHER `us-east-1` OR `us-west-2`.

### Nested Logic

Combine AND and OR:

```yaml theme={null}
resourceSelector: >-
  resource.metadata["environment"] == "production" &&
  (resource.metadata["region"] == "us-east-1" ||
   resource.metadata["region"] == "us-west-2")
```

Matches: `environment=production` AND (`region=us-east-1` OR `region=us-west-2`).

## CEL Expressions

Ctrlplane uses CEL (Common Expression Language) for all selectors:

```yaml theme={null}
resourceSelector: >-
  resource.metadata["environment"] == "production" &&
  resource.metadata["tier"] == "critical"
```

### CEL Basics

**Field Access**:

* `resource.metadata["environment"]` - Access metadata field
* `resource.kind` - Access kind field
* `resource.name` - Access name field
* `resource.identifier` - Access identifier field

**Operators**:

* `==`, `!=` - Equality
* `&&`, `||` - Logical AND/OR
* `!` - Logical NOT
* `<`, `>`, `<=`, `>=` - Comparison
* `in` - List membership
* `.matches()` - Regex match

**Examples**:

```yaml theme={null}
# Production OR Staging
resourceSelector: resource.metadata["environment"] in ["production", "staging"]

# Critical tier in production
resourceSelector: >-
  resource.metadata["environment"] == "production" &&
  resource.metadata["tier"] == "critical"

# Not deprecated
resourceSelector: >-
  !has(resource.metadata["deprecated"]) ||
  resource.metadata["deprecated"] != "true"

# Regex match on identifier
resourceSelector: resource.identifier.matches("^prod-cluster-[0-9]+$")

# Complex nested logic
resourceSelector: >-
  (resource.metadata["environment"] == "production" &&
   resource.metadata["region"] in ["us-east-1", "us-west-2"]) ||
  (resource.metadata["environment"] == "staging" &&
   resource.metadata["region"] == "us-east-1")
```

### CEL Best Practices

**Do**:

* ✅ Use CEL for complex nested logic
* ✅ Keep expressions readable with line breaks
* ✅ Test selectors before applying
* ✅ Reference the [CEL Reference](../reference/cel) for syntax

**Avoid**:

* ❌ Overly complex expressions that are hard to understand
* ❌ Expressions that might accidentally match wrong resources

## Selector Use Cases

### Environment Resource Selectors

Define which resources belong to an environment:

```yaml theme={null}
# Production environment
type: Environment
name: Production
resourceSelector: resource.metadata["environment"] == "production"
```

```yaml theme={null}
# Multi-region production
type: Environment
name: Production US East
resourceSelector: >-
  resource.metadata["environment"] == "production" &&
  resource.metadata["region"] == "us-east-1"
```

### Deployment Resource Selectors

Limit which resources a deployment can target:

```yaml theme={null}
# Kubernetes-only deployment
type: Deployment
name: Container Service
resourceSelector: resource.kind == "KubernetesCluster"
```

```yaml theme={null}
# Region-specific deployment
type: Deployment
name: US-Only Service
resourceSelector: resource.metadata["region"].matches("^us-.*")
```

### Policy Selectors

Target policies to specific deployments/environments/resources:

```yaml theme={null}
type: Policy
name: Production Approval Required
selectors:
  - environments: environment.name == "Production"
    deployments: deployment.metadata["critical"] == "true"
rules:
  - anyApproval:
      minApprovals: 2
```

This policy applies to critical deployments going to production.

## Testing Selectors

### Via CLI

Test a selector against your resources:

```bash theme={null}
ctrlc api get resources \
  --workspace {workspaceId} \
  --selector 'resource.metadata["environment"] == "production"'
```

Returns all resources matching the selector.

### Via Web UI

Most selector configuration screens have a "Test Selector" or "Preview Resources" button that shows which resources match.

## Common Selector Patterns

### Pattern 1: Environment-Based

```yaml theme={null}
resourceSelector: resource.metadata["environment"] == "production"
```

**Use Case**: Standard environment separation (dev/staging/prod).

### Pattern 2: Region-Based

```yaml theme={null}
resourceSelector: >-
  resource.metadata["environment"] == "production" &&
  resource.metadata["region"] == "us-east-1"
```

**Use Case**: Multi-region deployments, gradual regional rollout.

### Pattern 3: Team-Based

```yaml theme={null}
resourceSelector: resource.metadata["team"] == "platform"
```

**Use Case**: Team-specific resources and deployments.

### Pattern 4: Tier-Based

```yaml theme={null}
resourceSelector: resource.metadata["tier"] in ["critical", "high-priority"]
```

**Use Case**: SLA-based resource grouping.

### Pattern 5: Canary

```yaml theme={null}
resourceSelector: >-
  resource.metadata["environment"] == "production" &&
  resource.metadata["canary"] == "true"
```

**Use Case**: Canary deployment pattern.

### Pattern 6: Percentage-Based (using identifier)

```yaml theme={null}
resourceSelector: >-
  resource.metadata["environment"] == "production" &&
  resource.identifier.matches(".*[02468]$")
```

**Use Case**: Target resources with even-numbered identifiers (50% rollout).

## Best Practices

### Metadata Schema Design

Design your resource metadata with selectors in mind:

**Good Metadata Schema**:

```yaml theme={null}
# Recommended metadata keys
metadata:
  environment: production | staging | development
  region: us-east-1 | us-west-2 | eu-west-1
  zone: us-east-1a | us-east-1b | ...
  tier: critical | high | standard | low
  team: platform | product | data
  canary: "true" | "false"
```

**Why Good**:

* Consistent key names
* Enumerated values (not free-form)
* Multiple dimensions for targeting
* Clear, hierarchical organization

### Selector Simplicity

**Prefer Simple Selectors**:

```yaml theme={null}
resourceSelector: resource.metadata["environment"] == "production"
```

**Over Complex Ones**:

```yaml theme={null}
resourceSelector: >-
  resource.metadata["environment"] == "production" &&
  resource.metadata["region"].startsWith("us-") &&
  resource.metadata["tier"] == "critical" &&
  !has(resource.metadata["deprecated"])
```

Simple selectors are:

* Easier to understand
* Less error-prone
* More performant

### Document Complex Selectors

If you must use complex selectors, document them:

```yaml theme={null}
type: Environment
name: Production Critical
description: >-
  Targets production resources in US regions that are marked 
  critical tier and not deprecated
resourceSelector: >-
  resource.metadata["environment"] == "production" &&
  resource.metadata["region"].startsWith("us-") &&
  resource.metadata["tier"] == "critical" &&
  !has(resource.metadata["deprecated"])
```

### Test Before Applying

Always test selectors before using them:

1. Use the query API to see matched resources
2. Verify count matches expectations
3. Check for unexpected matches
4. Test in lower environment first

### Avoid Over-Matching

Be specific to avoid accidentally matching wrong resources:

**Too Broad**:

```yaml theme={null}
resourceSelector: resource.identifier.contains("prod")
```

Might match: `prod-cluster`, `product-server`, `reproduction-env`.

**Better**:

```yaml theme={null}
resourceSelector: resource.identifier.matches("^prod-.*")
```

Only matches identifiers starting with `prod-`.

## Troubleshooting

### Selector matches too many resources

* Make selector more specific (add conditions)
* Use AND instead of OR
* Add negation conditions
* Check resource metadata for unexpected values

### Selector matches too few resources

* Check metadata key names match exactly (case-sensitive)
* Verify resources have the expected metadata
* Use OR logic if resources vary
* Test with simpler selector first

### Selector matches nothing

* Verify selector syntax is correct
* Check resources exist with expected metadata
* Test each condition independently
* Review resource metadata in UI

### CEL expression errors

* Check syntax (use CEL validator)
* Verify field names are correct
* Test expression step-by-step
* Consult [CEL Reference](../reference/cel) or [CEL specification](https://github.com/google/cel-spec)

## Advanced Topics

### Selector Evaluation Order

When multiple selectors apply (e.g., environment + deployment):

1. Environment selector filters resources
2. Deployment selector (if present) filters further
3. Final set is intersection of both

### Selector Performance

Selectors are evaluated:

* When resources are created/updated
* When environments/deployments are created/updated
* When querying resources

**Performance Tips**:

* Simple selectors are faster than complex ones
* Metadata equality checks are very fast
* Regex matching is slower
* CEL expressions have some overhead

### Selector Caching

Ctrlplane caches selector evaluation results:

* Cache invalidated on resource/metadata changes
* Improves performance for repeated queries
* No manual cache management needed

## Next Steps

* [CEL Reference](../reference/cel) - Full CEL expression language reference
* [Environments](./environments) - Use selectors in environments
* [Deployments](./deployments) - Filter deployment targets
* [Resources](./resources) - Design resource metadata
* [Policies](../policies/overview) - Target policies with selectors
