# saif-utilities / naming

This module provides organized path structure for cloud resource naming. It contains no functionality itself - use the specific resource modules directly.

## Architecture

```
modules/naming/
├── base/                    # Provider-agnostic core naming logic
├── azure/                   # Azure-specific resource modules (path only)
│   ├── static/              # Static configuration data (functional)
│   └── servicebus/          # Service Bus resources (path only)
│       └── namespace/       # Service Bus Namespace naming (functional)
└── string_utilities/        # String casing utilities (functional)
    └── casing/              # String casing transformations (functional)
```

## Direct Module Usage

Always call specific functional modules directly:

### Azure Static Configuration

```terraform
module "static_config" {
  source = "app.terraform.io/SAIFCorp/utilities/saif//modules/naming/static"
}

# Access static data
locals {
  organization_name = module.static_config.organization_name
  environments      = module.static_config.Environments
  business_domains  = module.static_config.BusinessDomains
  tenants          = module.static_config.tenants
  services         = module.static_config.Services
}
```

### Azure ServiceBus Namespace

```terraform
module "servicebus_namespace_naming" {
  source = "app.terraform.io/SAIFCorp/utilities/saif//modules/naming/azure/servicebus/namespace"
  
  environment_short_name = "prod"
  tenant               = "mycompany"
  suffix               = ["001"]
}

resource "azurerm_servicebus_namespace" "main" {
  name                = module.servicebus_namespace_naming.name
  location            = "East US"
  resource_group_name = "my-resource-group"
  sku                 = "Standard"
}
```

## Variables

### Static Module

The static module requires no input variables - it provides read-only configuration data.

### Naming Modules

All naming modules share these core variables:

| Variable | Type | Description | Default |
|----------|------|-------------|---------|
| `Environment` | `string` | The environment for the resources (fallback value) | `""` |
| `environment_short_name` | `string` | The short name of the environment (takes precedence) | `""` |
| `tenant` | `string` | The tenant for the resources | `""` |
| `project_id` | `string` | The project id for the resources | `""` |
| `prefix` | `list(string)` | List of prefix components to add to resource names | `[]` |
| `suffix` | `list(string)` | List of suffix components to add to resource names | `[]` |
| `unique_length` | `number` | Max length of the uniqueness suffix | `4` |
| `unique_include_numbers` | `bool` | Include numbers in unique generation | `true` |

**Note:** The base module uses `environment_short_name` if it's not empty, otherwise falls back to `Environment`. This allows for flexibility in providing either short names (e.g., "prod") or full names (e.g., "production").

## Outputs

### Static Module Outputs

The static module provides organization-wide configuration data:

| Output | Description |
|--------|-------------|
| `organization_name` | Organization name (SAIF) |
| `Owners` | Team ownership information with names, short names, and descriptions |
| `tenantId` | tenant identifier |
| `Subscriptions` | Available subscription configurations |
| `SandboxSubscriptions` | Sandbox-specific subscription configurations |
| `TeamSubscriptions` | Team-owned development subscription configurations |
| `BusinessDomains` | Business domain definitions |
| `Environments` | Environment configurations (dev, test, uat, prod, etc.) |
| `tenants` | tenant configurations |
| `OktaEnvironments` | Okta-specific environment settings |
| `Services` | Service definitions including Azure service plans |
| `ApiTypes` | API type definitions |
| `ApplicationTypes` | Application type definitions |
| `Azure_AppServicePlans` | Azure App Service Plan configurations |
| `SubDomain_External` | External subdomain configurations |
| `SubDomain_Internal` | Internal subdomain configurations |

### Resource Output Structure

Each naming module output includes:

| Property | Description |
|----------|-------------|
| `name` | Standard name (kebab-case format) |
| `name_unique` | Name with unique suffix (kebab-case format) |
| `name_casings` | Object with all casing formats |
| `name_casings.Pascal` | Pascal case names (`{ name, name_unique }`) |
| `name_casings.Camel` | Camel case names (`{ name, name_unique }`) |
| `name_casings.Kebab` | Kebab case names (`{ name, name_unique }`) |
| `name_casings.Snake` | Snake case names (`{ name, name_unique }`) |
| `slug` | Resource type abbreviation (if used) |
| `dashes` | Whether dashes are used in formatting |
| `scope` | Uniqueness scope setting |
| `regex` | Name validation pattern used |

## Adding New Resources

### Adding Azure Resources

To add a new Azure resource, create the module structure:

```bash
# Create directory structure
mkdir -p modules/naming/azure/new_resource
cd modules/naming/azure/new_resource

# Create main.tf
cat > main.tf << 'EOF'
module "naming_base" {
  source = "../../base"

  resource_config = {
    slug   = ""                    # Resource abbreviation or "" for none
    dashes = true                  # Whether to allow dashes
    scope  = "global"              # global, resource_group, or subscription
    regex  = "^[a-zA-Z][a-zA-Z0-9-]{4,48}[a-zA-Z0-9]$"  # Validation pattern
  }

  Environment            = var.Environment
  environment_short_name   = var.environment_short_name
  tenant                 = var.tenant
  project_id              = var.project_id
  prefix                 = var.prefix
  suffix                 = var.suffix
  unique_length          = var.unique_length
  unique_include_numbers = var.unique_include_numbers
}
EOF

# Create variables.tf (copy from servicebus/namespace)
# Create output.tf (copy from servicebus/namespace and modify descriptions)
```

## Supported Azure Resources

Current Azure resources:

| Resource | Module Path | Regex Pattern | Scope |
|----------|-------------|---------------|-------|
| Service Bus Namespace | `azure/servicebus/namespace` | `^[a-zA-Z][a-zA-Z0-9-]{4,48}[a-zA-Z0-9]$` | global |

### Service Bus Namespace Details
- **Length**: 6-50 characters
- **Pattern**: Must start with a letter, end with letter/number, allow hyphens
- **Scope**: Global uniqueness required across all Azure
- **Slug**: None (empty string)

## Development

### Module Structure

Each resource module follows this structure:

```
resource_name/
├── variables.tf    # Standard variable definitions (same across all modules)
├── main.tf         # Calls base module with resource-specific config
└── output.tf       # Exposes resource naming outputs
```

### Resource Configuration

Each resource must define its configuration in the `resource_config` object:

```terraform
resource_config = {
  slug   = "abbreviation"       # Resource abbreviation (use "" for no slug)
  dashes = true                 # Whether dashes are allowed in names
  scope  = "global"            # Uniqueness scope: global, resource_group, subscription
  regex  = "^[pattern]$"       # Complete validation regex (replaces min/max length)
}
```

### Regex Patterns

The regex pattern enforces all naming rules:
- Length constraints (min/max are part of the pattern)
- Character restrictions (alphanumeric, hyphens, etc.)
- Format requirements (start/end character rules)

Example patterns:
```terraform
# 6-50 chars, start with letter, alphanumeric + hyphens
regex = "^[a-zA-Z][a-zA-Z0-9-]{4,48}[a-zA-Z0-9]$"

# 3-24 chars, lowercase alphanumeric only
regex = "^[a-z0-9]{3,24}$"

# 1-63 chars, DNS-compliant
regex = "^[a-z0-9]([a-z0-9-]*[a-z0-9])?$"
```

### Testing

Test each resource module with various inputs:
- Different environments and projects with varying lengths
- Long component combinations that test regex validation
- Special characters that test pattern compliance
- Global resources that need unique suffixes
- Edge cases for regex pattern boundaries

## Best Practices

1. **Modular Usage**: Use resource-specific modules for targeted naming needs
2. **Unique Names**: Always use `name_unique` for globally scoped resources
3. **Consistent Inputs**: Use the same naming variables across all your modules
4. **Regex Validation**: Design comprehensive regex patterns that enforce all requirements
5. **Documentation**: Update documentation when adding new resources
6. **Testing**: Validate regex patterns against cloud provider requirements

## Contributing

1. Follow the established module structure when adding resources
2. Use comprehensive regex patterns for validation
3. Include thorough testing with edge cases
4. Update documentation with examples
5. Maintain consistency with existing patterns

## Dependencies

- `../string_utilities/casing` - String casing utilities module
- Terraform >= 0.13

<!-- BEGIN_TF_DOCS -->
## Providers

No providers.

## Inputs

No inputs.

## Outputs

No outputs.

## Resources
    
<!-- END_TF_DOCS -->

---

[View source on GitHub](https://github.com/saif-corp/forge/blob/main/src/terraform/saif-utilities/modules/naming/README.md)
