# 機能設計書 458-Add-DbaRegServerGroup

## 概要

本ドキュメントは、dbatools PowerShellモジュールにおける`Add-DbaRegServerGroup`関数の機能設計を定義する。この関数はSQL Server Central Management Server (CMS)またはローカル登録サーバーグループに新しいサーバーグループを作成し、SQL Serverインスタンスの階層的な整理を可能にする。

### 本機能の処理概要

**業務上の目的・背景**：大規模なSQL Server環境では、多数のインスタンスを論理的にグループ化して管理する必要がある。Central Management Serverのサーバーグループ機能を活用することで、環境別（本番/開発/テスト）、機能別（Web/DB/レポート）、地域別などの分類が可能になる。本関数は、このグループ作成を自動化し、大量のサーバー登録作業を効率化する。

**機能の利用シーン**：
- 新しい管理カテゴリの追加時
- 複数CMSサーバーへの一括グループ作成時
- CI/CD パイプラインでのCMS構成自動化時
- 既存グループへのサブグループ追加時

**主要な処理内容**：
1. 対象CMSインスタンスまたはローカルストアの特定
2. 親グループの取得（指定がある場合）
3. バックスラッシュ記法でのネストグループ対応
4. ServerGroupオブジェクトの作成と永続化
5. 作成結果の出力

**関連システム・外部連携**：SQL Server Management Objects (SMO) RegisteredServers名前空間、SQL Server Central Management Server

**権限による制御**：CMSサーバーへの接続権限が必要。ローカル操作時は特別な権限不要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | SQL Server Management Studio - 登録済みサーバー | 参照画面 | サーバーグループ作成操作に相当 |
| N/A | Azure Data Studio - サーバーグループ | 参照画面 | サーバーグループ管理（操作不可） |

## 機能種別

CRUD操作（Create） / CMS構成管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | No* | CMSサーバーSQL Serverインスタンス | InputObjectと排他 |
| SqlCredential | PSCredential | No | SQL Server認証用資格情報 | 有効な認証情報 |
| Name | String | Yes | 作成するグループ名 | 空文字不可 |
| Description | String | No | グループの説明 | なし |
| Group | String | No | 親グループ名（バックスラッシュでネスト可） | 有効なグループパス |
| InputObject | ServerGroup[] | No* | パイプライン入力用のServerGroupオブジェクト | パイプライン入力対応 |
| EnableException | Switch | No | 例外を有効化 | なし |

*SqlInstance または InputObject のいずれか、または両方省略でローカルストア操作

### 入力データソース

- パラメータ入力
- Get-DbaRegServerGroupからのパイプライン入力
- ローカル登録サーバーストア

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | String | CMSホストのコンピュータ名 |
| InstanceName | String | CMSインスタンス名 |
| SqlInstance | String | フルCMSインスタンス名 |
| Name | String | グループ名 |
| DisplayName | String | 表示名 |
| Description | String | グループ説明 |
| ServerGroups | Collection | 子グループコレクション |
| RegisteredServers | Collection | 登録サーバーコレクション |

### 出力先

パイプラインに作成されたServerGroupオブジェクトを出力

## 処理フロー

### 処理シーケンス

```
1. 入力ソースの特定
   ├─ SqlInstance指定時: Get-DbaRegServerGroupでグループ取得
   │   ├─ Group指定あり: 指定グループを取得
   │   └─ Group指定なし: ルートグループ（ID=1）を取得
   └─ SqlInstance未指定時: ローカルストア使用
2. Azure Data Studioチェック
   └─ Source = "Azure Data Studio"の場合はエラー（操作不可）
3. 各親グループに対する処理（foreach）
   ├─ ShouldProcess確認
   ├─ グループ名のバックスラッシュ分割
   ├─ 各階層でグループ作成/取得
   │   ├─ 存在しない場合: New-Object ServerGroup → Create()
   │   └─ 存在する場合: 既存グループ使用（継続）
   ├─ 最終グループにDescription設定
   └─ Alter()で変更確定
4. 作成結果の出力
   └─ Get-DbaRegServerGroupで結果取得
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{SqlInstance指定?}
    B -->|Yes| C{Group指定?}
    B -->|No| D{InputObject指定?}
    C -->|Yes| E[Get-DbaRegServerGroup Group]
    C -->|No| F[Get-DbaRegServerGroup Id=1]
    D -->|Yes| G[InputObject使用]
    D -->|No| H[ローカルストア使用]
    E --> I[InputObject += 結果]
    F --> I
    G --> J[foreach reggroup]
    H --> K{Group指定?}
    K -->|Yes| L[Get-DbaRegServerGroup Group]
    K -->|No| M[Get-DbaRegServerGroup Id=1]
    L --> J
    M --> J
    I --> J
    J --> N{Azure Data Studio?}
    N -->|Yes| O[エラー終了]
    N -->|No| P[ShouldProcess確認]
    P -->|No| Q[スキップ]
    P -->|Yes| R[Name分割（\）]
    R --> S[foreach group in groupList]
    S --> T{グループ存在?}
    T -->|No| U[New-Object ServerGroup]
    U --> V[Create]
    V --> W[refresh]
    T -->|Yes| X[既存グループ使用]
    W --> Y[次の階層へ]
    X --> Y
    Y --> S
    S -->|完了| Z[Description設定]
    Z --> AA[Alter]
    AA --> AB[Get-DbaRegServerGroup]
    AB --> AC[結果出力]
    Q --> AD[次のreggroup]
    AC --> AD
    AD --> J
    J -->|完了| AE[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | ネストグループ対応 | バックスラッシュ（\）でグループ名を区切り、階層的にグループを作成 | Name にバックスラッシュ含む場合 |
| BR-002 | 既存グループスキップ | 同名のグループが存在する場合はエラーにせず、そのグループを使用して続行 | 常時適用 |
| BR-003 | Azure Data Studio制限 | Azure Data Studioのサーバーグループは追加/削除不可 | Source = "Azure Data Studio" |
| BR-004 | ローカルストアフォールバック | SqlInstance未指定でInputObjectもない場合はローカルストアを使用 | パラメータ未指定時 |

### 計算ロジック

特になし

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| グループ作成 | CMS内部ストア | INSERT | ServerGroupの永続化 |
| 説明更新 | CMS内部ストア | UPDATE | Descriptionの設定 |

CMSはmsdb.dbo.sysmanagement_shared_server_groups テーブルに情報を格納

### テーブル別操作詳細

#### sysmanagement_shared_server_groups (msdb)

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | Nameパラメータ値 | グループ名 |
| INSERT | description | Descriptionパラメータ値 | 説明 |
| INSERT | parent_id | 親グループID | 階層構造 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | Azure Data Studio制限 | Source = "Azure Data Studio" | dbatoolsからの操作不可 |
| N/A | 接続エラー | CMSサーバー接続失敗 | 接続情報確認 |
| N/A | 作成エラー | ServerGroup.Create()失敗 | 権限確認 |

### リトライ仕様

本関数にリトライ機能は実装されていない。

## トランザクション仕様

Create()およびAlter()は個別操作で実行。途中でエラーが発生した場合、それ以前に作成されたグループは維持される。

## パフォーマンス要件

グループ作成は即座に完了。ネストが深い場合は階層数に比例した処理時間。

## セキュリティ考慮事項

- CMSサーバーへの適切な接続権限が必要
- SqlCredentialはSecureStringとして処理
- ローカルストア操作時はOSレベルのファイルアクセス権限のみ必要

## 備考

- Azure Data Studioのサーバーグループは読み取り専用
- 作成後のグループパスはGet-RegServerGroupReverseParse内部関数で解析
- ローカルストア情報はSSMSの設定ファイルに保存される

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: 関数構造とパラメータを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Add-DbaRegServerGroup.ps1 | `public/Add-DbaRegServerGroup.ps1` | param()ブロック（94-105行目） |

**読解のコツ**: `[parameter(Mandatory)]`がNameのみに付いていることに注意。SqlInstanceとInputObjectは両方オプション。

#### Step 2: 入力ソース決定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Add-DbaRegServerGroup.ps1 | `public/Add-DbaRegServerGroup.ps1` | processブロック前半（107-121行目） |

**主要処理フロー**:
1. **107-112行目**: SqlInstance指定時のGet-DbaRegServerGroup呼び出し
2. **115-121行目**: SqlInstance/InputObject両方未指定時のローカルストア取得

#### Step 3: グループ作成ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Add-DbaRegServerGroup.ps1 | `public/Add-DbaRegServerGroup.ps1` | processブロック後半（123-161行目） |

**主要処理フロー**:
- **124-126行目**: Azure Data Studioチェック
- **136行目**: ShouldProcess確認
- **138行目**: グループ名のバックスラッシュ分割
- **139-149行目**: 各階層でのグループ作成/取得ループ
- **150-151行目**: Description設定とAlter()

### プログラム呼び出し階層図

```
Add-DbaRegServerGroup
    │
    ├─ Get-DbaRegServerGroup
    │      ├─ -Group 指定時: 特定グループ取得
    │      └─ -Id 1 指定時: ルートグループ取得
    │
    └─ [process] foreach (reggroup)
           │
           ├─ [SMO] ServerGroup (各階層)
           │      ├─ New-Object ServerGroup(parent, name)
           │      ├─ Create()
           │      └─ refresh()
           │
           ├─ [SMO] ServerGroup (最終階層)
           │      ├─ Description = ...
           │      └─ Alter()
           │
           └─ Get-DbaRegServerGroup (結果取得)
                  └─ Get-RegServerGroupReverseParse
```

### データフロー図

```
[入力]                              [処理]                              [出力]

SqlInstance ─────────────────▶ Get-DbaRegServerGroup ────────────────▶ 親グループ取得
Group ───────────────────────────────┘                                  │
                                   │                                    │
InputObject ─────────────────▶ 配列に追加 ──────────────────────────────┤
                                   │                                    │
                             foreach (reggroup) ◀───────────────────────┘
                                   │
Name ────────────────────────▶ Split('\') ───────────────────────────▶ 階層分割
                                   │
                             foreach (group in groupList)
                                   │
                                   ├─ (未存在) New-Object ServerGroup ─▶ グループ作成
                                   │           Create()
                                   │
                                   └─ (存在) 既存グループ使用 ──────────▶ 次階層へ
                                   │
Description ─────────────────▶ newgroup.Description = ... ───────────▶ 説明設定
                                   │
                             Alter() ─────────────────────────────────▶ 永続化
                                   │
                             Get-DbaRegServerGroup ───────────────────▶ ServerGroup
                                                                        オブジェクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Add-DbaRegServerGroup.ps1 | `public/Add-DbaRegServerGroup.ps1` | ソース | メイン関数定義 |
| Get-DbaRegServerGroup.ps1 | `public/Get-DbaRegServerGroup.ps1` | ソース | グループ情報取得 |
| Get-DbaRegServerStore.ps1 | `public/Get-DbaRegServerStore.ps1` | ソース | ストアオブジェクト取得 |
| Remove-DbaRegServerGroup.ps1 | `public/Remove-DbaRegServerGroup.ps1` | ソース | 対となるグループ削除機能 |
