# Using expr

Bluebricks leverages the [expr](https://expr-lang.org/) expression language to enable dynamic configurations within your `bricks.json` files. This allows for powerful manipulations, conditional logic, and more.

## What is expr?

[expr](https://expr-lang.org/) is a lightweight, high-performance expression language for Go, designed for dynamic evaluation of expressions. In Bluebricks, it lets you:

* Perform arithmetic and string operations
* Use conditional logic (if/else, ternary)
* Access built-in functions for manipulating strings, lists, maps, etc.
* Reference properties, data, and secrets dynamically

## Common Use Cases

* **Basic arithmetic and string operations**: Concatenation, addition, subtraction, etc.
* **Conditional expressions**: Ternary operators or if/else logic.
* **Functions**: Built-in functions for manipulating strings, lists, maps, etc.

## Examples

### 1. Concatenating strings and using current time

```json
{
  "packages": [
    {
      "name": "my_s3_bucket",
      "version": "1.0.0",
      "props": {
        "bucket_name": {
            "value": "now().Format('02012006030405')+'_sample_bucket'+(Props.vpc_id ?? Data.vpc1.vpc_id)"
        }
      }
    }
  ]
}
```

* `now().Format('02012006030405')` generates a timestamp string.
* `'_sample_bucket'` is a static string.
* `(Props.vpc_id ?? Data.vpc1.vpc_id)` uses the null coalescing operator: it will use `Props.vpc_id` if defined, otherwise `Data.vpc1.vpc_id`.

### 2. Conditional Logic (Ternary Operator)

```json
{
  "props": {
    "environment": {
      "type": "string",
      "default": "dev"
    }
  },
  "packages": [
    {
      "name": "my_instance",
      "version": "1.0.0",
      "props": {
        "instance_type": {
            "value": "Props.environment == 'prod' ? 'm5.xlarge' : 't3.medium'"
      }
    }
  ]
}
```

This sets `instance_type` to `m5.xlarge` if `Props.environment` is `prod`, otherwise `t3.medium`.

### 3. Accessing nested properties and list elements

```json
{
  "props": {
    "network_config": {
      "type": "object",
      "default": {
        "subnets": ["subnet-abc", "subnet-def"],
        "security_groups": ["sg-123"]
      }
    }
  },
  "packages": [
    {
      "name": "my_service",
      "version": "1.0.0",
      "props": {
        "subnet_id": { "value": "Props.network_config.subnets[0]" },
        "security_group_id": { "value": "Props.network_config.security_groups[0]" }
      }
    }
  ]
}
```

### 4. Null coalescing for fallbacks

Use the `??` operator to provide fallback values:

```json
{
  "packages": [
    {
      "name": "@bluebricks/terraform_aws_subnet",
      "id": "web_subnet",
      "props": {
        "vpc_id": {
          "value": "Props.vpc_id ?? Data.shared_vpc.vpc_id"
        },
        "availability_zone": {
          "value": "Props.az ?? 'us-west-2a'"
        }
      }
    }
  ]
}
```

`Props.vpc_id ?? Data.shared_vpc.vpc_id` uses `Props.vpc_id` if defined, otherwise falls back to `Data.shared_vpc.vpc_id`.

### 5. String concatenation

Build complex strings from multiple sources:

```json
{
  "packages": [
    {
      "name": "@bluebricks/terraform_aws_route53",
      "id": "dns_record",
      "props": {
        "domain_name": {
          "value": "Props.service_name + '.' + Props.environment + '.' + Props.base_domain"
        }
      }
    }
  ]
}
```

### 6. Mathematical operations

Perform calculations for resource sizing:

```json
{
  "packages": [
    {
      "name": "@bluebricks/terraform_aws_instance",
      "id": "web_servers",
      "props": {
        "count": {
          "value": "Props.environment == 'prod' ? Props.base_instance_count * 2 : Props.base_instance_count"
        }
      }
    }
  ]
}
```

### 7. Complex conditional logic

Combine multiple conditions:

```json
{
  "packages": [
    {
      "name": "@bluebricks/terraform_aws_alb",
      "id": "load_balancer",
      "props": {
        "ssl_certificate_arn": {
          "value": "Props.enable_ssl && Props.environment == 'prod' ? Secrets.prod_ssl_cert : (Props.enable_ssl ? Secrets.dev_ssl_cert : '')"
        }
      }
    }
  ]
}
```

### 8. Output aggregation with expressions

Combine outputs from multiple packages:

```json
{
  "outs": {
    "all_endpoints": {
      "value": "Data.web_server.endpoint + ',' + Data.api_server.endpoint + ',' + Data.admin_server.endpoint",
      "type": "string",
      "description": "All service endpoints"
    },
    "monitoring_dashboard": {
      "value": "Props.enable_monitoring ? Data.monitoring.dashboard_url : 'Monitoring disabled'",
      "type": "string",
      "description": "Monitoring dashboard URL or status"
    }
  }
}
```

## Best practices

* Use expressions for dynamic values, not static ones
* Keep expressions readable; avoid deeply nested ternaries
* Use null coalescing (`??`) for safe fallbacks
* Test complex expressions with different input combinations

## Further reading

* [expr language documentation](https://expr-lang.org/docs/language-definition#operators)
* [expr playground](https://expr-lang.org/playground)
* [Blueprint Composition Patterns](/docs/orchestration/packages/blueprints-overview/blueprint-composition-patterns.md): architectural patterns that use expressions in context


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bluebricks.co/docs/orchestration/packages/blueprints-overview/expr.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
