Skip to content
Merged
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
4 changes: 3 additions & 1 deletion docs/v5.0.0/RELEASE_NOTES_v5.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,16 @@ Version 5.0.0 is a major release featuring .NET 10.0 framework upgrade, modern d
- Improved visual hierarchy and card-based design

### SQLite Database Support
- **Optional upgrade** - SQLite available for enhanced performance (not default)
- **Enhanced performance** with faster data access and queries
- **Better scalability** for larger configurations
- **Improved reliability** with transactional support and data integrity
- **Built-in migration tool** from file-based storage to SQLite
- **One-click migration** with automatic backup creation
- **Rollback support** if migration issues occur
- Admin UI for easy storage provider management
- Maintains backward compatibility with file-based JSON storage
- **Default remains JSON file-based storage** for maximum compatibility
- ⚠️ **IMPORTANT**: SQLite not recommended for Azure Container Apps with File Share mounts (use FileSystem storage instead)

### Azure Tenant Name Validation
- **Validate generated names against your Azure tenant** before deployment
Expand Down
115 changes: 96 additions & 19 deletions docs/v5.0.0/V5.0.0_MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# Azure Naming Tool v5.0.0 Migration Guide

## Overview

Version 5.0.0 of the Azure Naming Tool introduces significant enhancements including a modern redesigned UI, SQLite database storage option, and Azure resource name validation capabilities. This guide will help you successfully migrate from previous versions to v5.0.0.
Expand Down Expand Up @@ -279,20 +277,42 @@ v5.0.0 requires .NET 10.0 runtime. You **MUST** update your App Service runtime

**⚠️ IMPORTANT: .NET 10.0 Docker Image Required**

v5.0.0 uses a new Docker image based on .NET 10.0 runtime.
v5.0.0 uses a new Docker image based on .NET 10.0 runtime. You need to build the image locally from source.

**🚨 CRITICAL - Azure Container Apps Users:**

If you are deploying to **Azure Container Apps with Azure File Share** for persistent storage:

> **DO NOT use SQLite storage!**
>
> SQLite does not work with Azure File Share (SMB/CIFS network mounts) due to file locking issues. Your container will fail to start with `"database is locked"` errors.
>
> **Solution:** Use FileSystem (JSON) storage instead:
> - In `appsettings.json`, ensure: `"StorageProvider": "FileSystem"`
> - This is the default for fresh Docker installations
> - JSON files work perfectly with Azure File Share mounts
> - You can still use all v5.0.0 features except Azure Tenant Name Validation (which requires SQLite)

**For other Docker deployments:** SQLite works fine with local Docker volumes.

1. **STOP the current container (if running):**
```bash
docker stop azurenamingtool
docker rm azurenamingtool
```

2. **Pull the latest v5.0.0 image:**
2. **Clone the repository and build the v5.0.0 image:**
```bash
# Pull the .NET 10.0-based image
docker pull ghcr.io/mspnp/azurenamingtool:v5.0.0
# Or use latest tag (ensure it's v5.0.0 or higher)
docker pull ghcr.io/mspnp/azurenamingtool:latest
# Clone the repository (if not already cloned)
git clone https://github.com/mspnp/AzureNamingTool.git
cd AzureNamingTool

# Checkout the v5.0.0 release tag
git checkout v5.0.0

# Build the Docker image from the src directory
cd src
docker build -t azurenamingtool:v5.0.0 .
```

3. **Run with persistent storage:**
Expand All @@ -303,7 +323,7 @@ v5.0.0 uses a new Docker image based on .NET 10.0 runtime.
-v $(pwd)/settings:/app/settings \
--name azurenamingtool \
--restart unless-stopped \
ghcr.io/mspnp/azurenamingtool:v5.0.0
azurenamingtool:v5.0.0
```

**Windows PowerShell:**
Expand All @@ -314,10 +334,10 @@ v5.0.0 uses a new Docker image based on .NET 10.0 runtime.
-v ${PWD}/settings:/app/settings `
--name azurenamingtool `
--restart unless-stopped `
ghcr.io/mspnp/azurenamingtool:v5.0.0
azurenamingtool:v5.0.0
```

4. **Verify container started:**
5. **Verify container started:**

Copilot AI Dec 11, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Numbering error in the deployment steps. The list jumps from step 3 to step 5, skipping step 4. This should be renumbered to step 4 instead of step 5 to maintain proper sequence.

Suggested change
5. **Verify container started:**
4. **Verify container started:**

Copilot uses AI. Check for mistakes.
```bash
# Check container is running
docker ps
Expand All @@ -328,25 +348,25 @@ v5.0.0 uses a new Docker image based on .NET 10.0 runtime.
# Should see: "Now listening on: http://[::]:80"
```

5. Wait 30-60 seconds, then access the application at `http://localhost`
6. Access the application at `http://localhost:8081` (or your chosen port)

Copilot AI Dec 11, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Numbering error in the deployment steps. This should be step 5 (not step 6) to maintain proper sequence after fixing step 4.

Copilot uses AI. Check for mistakes.

6. **VERIFY DEPLOYMENT:**
- Check container logs: `docker logs azurenamingtool | grep "Application started"`
- Access http://localhost and verify v5.0.0 loads
7. **VERIFY DEPLOYMENT:**

Copilot AI Dec 11, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Numbering error in the deployment steps. This should be step 6 (not step 7) to maintain proper sequence after fixing the previous steps.

Suggested change
7. **VERIFY DEPLOYMENT:**
6. **VERIFY DEPLOYMENT:**

Copilot uses AI. Check for mistakes.
- Check container logs: `docker logs azurenamingtool`
- Access http://localhost:8081 and verify v5.0.0 loads
- Check footer for version "5.0.0"

**Docker Compose Example:**
```yaml
version: '3.8'
services:
azurenamingtool:
image: ghcr.io/mspnp/azurenamingtool:v5.0.0
build: . # Build from local Dockerfile

Copilot AI Dec 11, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docker Compose build context may be unclear. The step-by-step instructions tell users to cd src before running docker build, but the Docker Compose example uses build: . without specifying which directory to run docker-compose from. Since the Dockerfile is in the src/ directory, the docker-compose.yml should either be placed in the src/ directory, or the build context should be explicitly set to ./src in the compose file (e.g., build: ./src or build: { context: ./src }). Consider adding a note clarifying where to place or run the docker-compose.yml file.

Copilot uses AI. Check for mistakes.
image: azurenamingtool:latest
container_name: azurenamingtool
ports:
- "80:80"
- "8081:80" # Map host port 8081 to container port 80
volumes:
- ./repository:/app/repository
- ./settings:/app/settings
- azurenamingtoolvol:/app/settings # Use Docker volume for persistence
restart: unless-stopped
environment:
- ASPNETCORE_ENVIRONMENT=Production
Expand Down Expand Up @@ -574,6 +594,25 @@ v5.0.0 introduces SQLite database support for improved performance and reliabili
> - The application **MUST BE RESTARTED** after migration completes
> - Ensure you have adequate disk space (at least 2x your current data size)

> **🚨 CRITICAL - Azure Container Apps & File Share Users:**
>
> **DO NOT migrate to SQLite if you are using:**
> - **Azure Container Apps with Azure File Share** mounted volumes
> - **Any network file system** (SMB/CIFS/NFS) for persistent storage
> - **Docker with bind mounts to network drives**
>
> **Why:** SQLite does not support network file systems due to file locking limitations. The database file will become locked and your container will fail to start with error: `"database is locked"`.
>
> **Solution:** Keep using **FileSystem (JSON)** storage provider for these scenarios. JSON file storage works perfectly with network mounts.
>
> **When SQLite works:**
> - ✅ Azure App Service (local disk)
> - ✅ Docker with Docker volumes (local)
> - ✅ Standalone installations (local disk)
> - ✅ Kubernetes with local persistent volumes
> - ❌ Azure Container Apps with File Share
> - ❌ Any network-based storage

#### Prerequisites

1. **Complete Steps 1-5** (Deploy v5.0.0 and restore configuration)
Expand Down Expand Up @@ -746,6 +785,44 @@ If you need to rollback from SQLite to file-based storage:
4. Try rollback procedure (see Step 6)
5. Restore from pre-migration backup

#### Container Fails with "Database is Locked" Error
**Symptom:** Docker container or Azure Container App fails to start with SQLite error: `"SQLite Error 5: 'database is locked'"` or `"Microsoft.Data.Sqlite.SqliteException (0x80004005)"`

**Root Cause:** SQLite does not support network file systems (Azure File Share uses SMB/CIFS protocol). File locking doesn't work correctly over network mounts.

**Solution:**
1. **Immediate Fix - Switch to FileSystem Storage:**
```bash
# Stop the container
docker stop azurenamingtool
docker rm azurenamingtool

# Edit settings/appsettings.json and change:
"StorageProvider": "FileSystem" # Change from "SQLite"

# Delete the SQLite database file (optional, but recommended)
rm settings/azurenamingtool.db

# Restart container
docker run -d \
-p 8081:80 \
--mount source=azurenamingtoolvol,target=/app/settings \
--name azurenamingtool \
azurenamingtool:latest
```

2. **For Azure Container Apps:**
- Keep using FileSystem (JSON) storage
- Do NOT migrate to SQLite
- JSON files work perfectly with Azure File Share

3. **Long-term Solution:**
- Use FileSystem storage for Azure Container Apps with File Share
- OR migrate to Azure App Service with local disk for SQLite support
- OR use Azure SQL Database (future enhancement)

**Prevention:** Always check deployment platform before migrating to SQLite (see warning in Step 6).

#### Azure Validation Not Working
**Symptom:** Azure validation features are not available

Expand Down
65 changes: 36 additions & 29 deletions docs/v5.0.0/wiki/V5.0.0_MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,45 +279,52 @@ v5.0.0 requires .NET 10.0 runtime. You **MUST** update your App Service runtime

**⚠️ IMPORTANT: .NET 10.0 Docker Image Required**

v5.0.0 uses a new Docker image based on .NET 10.0 runtime.
v5.0.0 uses a new Docker image based on .NET 10.0 runtime. You must build the image from source.

1. **STOP the current container (if running):**
```bash
docker stop azurenamingtool
docker rm azurenamingtool
```

2. **Pull the latest v5.0.0 image:**
2. **Download and extract v5.0.0 release:**
- Navigate to the [Releases page](https://github.com/mspnp/AzureNamingTool/releases)
- Download **AzureNamingTool.zip** from the v5.0.0 release assets
- Extract the ZIP file to a folder
- Verify the extracted files match the repository contents

3. **Build the v5.0.0 Docker image:**
```bash
# Pull the .NET 10.0-based image
docker pull ghcr.io/mspnp/azurenamingtool:v5.0.0
# Or use latest tag (ensure it's v5.0.0 or higher)
docker pull ghcr.io/mspnp/azurenamingtool:latest
# Navigate to the extracted folder
cd path/to/extracted/AzureNamingTool

# Build the Docker image
docker build -t azurenamingtool .
```

> **NOTE:** Ensure the '.' is included in the command

3. **Run with persistent storage:**
4. **Run with persistent storage using a Docker volume:**
```bash
docker run -d \
-p 80:80 \
-v $(pwd)/repository:/app/repository \
-v $(pwd)/settings:/app/settings \
-p 8081:80 \
--mount source=azurenamingtoolvol,target=/app/settings \
--name azurenamingtool \
--restart unless-stopped \
ghcr.io/mspnp/azurenamingtool:v5.0.0
azurenamingtool:latest
```

**Windows PowerShell:**
```powershell
docker run -d `
-p 80:80 `
-v ${PWD}/repository:/app/repository `
-v ${PWD}/settings:/app/settings `
--name azurenamingtool `
--restart unless-stopped `
ghcr.io/mspnp/azurenamingtool:v5.0.0
**Windows Command Prompt:**
```cmd
docker run -d -p 8081:80 --mount source=azurenamingtoolvol,target=/app/settings --name azurenamingtool --restart unless-stopped azurenamingtool:latest
```

> **NOTES:**
> - Substitute 8081 for any port not in use on your machine
> - The volume mount ensures settings persist across container restarts
> - You may see warnings about DataProtection keys - these are normal and indicate keys are local to the container

4. **Verify container started:**
5. **Verify container started:**
```bash
# Check container is running
docker ps
Expand All @@ -328,25 +335,25 @@ v5.0.0 uses a new Docker image based on .NET 10.0 runtime.
# Should see: "Now listening on: http://[::]:80"
```

5. Wait 30-60 seconds, then access the application at `http://localhost`
6. Access the application at `http://localhost:8081` (or your chosen port)

6. **VERIFY DEPLOYMENT:**
- Check container logs: `docker logs azurenamingtool | grep "Application started"`
- Access http://localhost and verify v5.0.0 loads
7. **VERIFY DEPLOYMENT:**
- Check container logs: `docker logs azurenamingtool`
- Access http://localhost:8081 and verify v5.0.0 loads
- Check footer for version "5.0.0"

**Docker Compose Example:**
```yaml
version: '3.8'
services:
azurenamingtool:
image: ghcr.io/mspnp/azurenamingtool:v5.0.0
build: . # Build from local Dockerfile

Copilot AI Dec 11, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docker Compose build context may be unclear. The step-by-step instructions tell users to build from an extracted folder using docker build -t azurenamingtool . in the AzureNamingTool directory, but the Docker Compose example uses build: . without specifying which directory to run docker-compose from. If the Dockerfile is in the src/ subdirectory, users need to know whether to place the docker-compose.yml in the root directory and use build: ./src, or place it in the src directory. Consider adding clarification about the build context or file placement.

Copilot uses AI. Check for mistakes.
image: azurenamingtool:latest
container_name: azurenamingtool
ports:
- "80:80"
- "8081:80" # Map host port 8081 to container port 80
volumes:
- ./repository:/app/repository
- ./settings:/app/settings
- azurenamingtoolvol:/app/settings # Use Docker volume for persistence
restart: unless-stopped
environment:
- ASPNETCORE_ENVIRONMENT=Production
Expand Down
14 changes: 14 additions & 0 deletions src/Components/Modals/MigrationPromptModal.razor
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,20 @@
</div>
</div>

<div class="modern-notification-danger" style="margin-bottom: 1rem;">
<i class="bi bi-exclamation-triangle-fill"></i>
<div>
<strong>⚠️ CRITICAL - Azure Container Apps Users:</strong>
<p style="margin: 0.5rem 0 0 0;">
<strong>DO NOT migrate to SQLite</strong> if you are using <strong>Azure Container Apps with Azure File Share</strong> for persistent storage.
SQLite does not work with network file systems (Azure File Share uses SMB/CIFS) and will cause "database is locked" errors.
</p>
<p style="margin: 0.5rem 0 0 0;">
<strong>Keep using JSON (FileSystem)</strong> storage for Azure Container Apps deployments with File Share.
</p>
</div>
</div>

@if (showMigrationStatus)
{
<div class="modern-notification-warning">
Expand Down
8 changes: 4 additions & 4 deletions src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,17 +290,17 @@
else
{
// No settings/appsettings.json = Fresh install
// VerifyConfiguration will copy repository/appsettings.json with StorageProvider=SQLite
Console.WriteLine("[Storage] Fresh install detected - will use default (SQLite)");
// VerifyConfiguration will copy repository/appsettings.json with StorageProvider=FileSystem (default)
Console.WriteLine("[Storage] Fresh install detected - will use default (FileSystem)");
}

// Run VerifyConfiguration to ensure all config files exist
// For fresh installs, this copies repository/appsettings.json → settings/appsettings.json (with StorageProvider=SQLite)
// For fresh installs, this copies repository/appsettings.json → settings/appsettings.json (with StorageProvider=FileSystem)
ConfigurationHelper.VerifyConfiguration(new StateContainer());

// Read the configuration and use the StorageProvider value
var siteConfig = ConfigurationHelper.GetConfigurationData();
var provider = siteConfig.StorageProvider?.ToLower() ?? "sqlite";
var provider = siteConfig.StorageProvider?.ToLower() ?? "filesystem";

if (provider == "sqlite")
{
Expand Down
2 changes: 1 addition & 1 deletion src/repository/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@
"GeneratedNamesLogEnabled": "True",
"InstructionsEnabled": "True",
"IdentityHeaderName": "X-MS-CLIENT-PRINCIPAL-NAME",
"StorageProvider": "SQLite"
"StorageProvider": "FileSystem"
}
Loading