# 通知設計書 23-New-DbaAgentOperator

## 概要

本ドキュメントは、SQL Server Agentオペレーターを新規作成するPowerShellコマンド `New-DbaAgentOperator` の通知設計書です。

### 本通知の処理概要

`New-DbaAgentOperator` は、SQL Server Agentにアラートやジョブ失敗の通知を受信する新しいオペレーター（連絡先）を作成するコマンドです。メール、ページャー、NetSendによる通知設定と、曜日別のページャースケジュールを構成できます。

**業務上の目的・背景**：SQL Server Agentのオペレーターは、アラート発生時やジョブ失敗時に通知を受け取る連絡先として機能します。新しいDBAチームメンバーの追加、オンコール担当者のローテーション、または新しい監視体制の構築時に、手動でSSMSを操作する代わりにスクリプトによる一貫したオペレーター作成を実現します。複数インスタンスへの一括作成も可能で、環境間の設定統一に貢献します。

**通知の送信タイミング**：このコマンドはオペレーターを作成する機能であり、作成時に通知は送信されません。コマンド実行完了後、作成されたオペレーターオブジェクト（SMO Operator）がパイプラインに出力されます。

**通知の受信者**：コマンド実行者がPowerShellコンソールまたはスクリプトの出力を通じて結果を受信します。作成されたオペレーターは、将来的にアラートやジョブから通知を受信する設定として機能します。

**通知内容の概要**：出力には作成されたオペレーターのSMOオブジェクトが含まれ、デフォルト表示プロパティとして：ComputerName、InstanceName、SqlInstance、Name、EmailAddress、NetSendAddress、PagerAddress、Enabled、LastEmailDate、LastNetSendDate、LastPagerDateが表示されます。

**期待されるアクション**：コマンド実行者は作成されたオペレーターをアラートやジョブの通知先として設定し、通知システムが正しく機能することを確認することが期待されます。必要に応じてSet-DbaAgentOperatorで設定を調整します。

## 通知種別

コンソール出力 / パイプライン出力（Microsoft.SqlServer.Management.Smo.Agent.Operator）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（処理完了後にパイプライン出力） |
| 優先度 | 中 |
| リトライ | 無（-Forceパラメータで既存の削除・再作成が可能） |

### 送信先決定ロジック

コマンド実行者のPowerShellセッションに直接出力されます。作成完了後、Get-DbaAgentOperatorを内部的に呼び出して作成されたオペレーターを取得し出力します。

## 通知テンプレート

### コンソール出力の場合

| 項目 | 内容 |
|-----|------|
| 出力形式 | Microsoft.SqlServer.Management.Smo.Agent.Operator |
| デフォルト表示プロパティ | ComputerName, InstanceName, SqlInstance, Name, EmailAddress, NetSendAddress, PagerAddress, Enabled, LastEmailDate, LastNetSendDate, LastPagerDate |

### 作成時に設定可能なプロパティ

```powershell
$operators = New-Object Microsoft.SqlServer.Management.Smo.Agent.Operator($JobServer, $Operator)
$operators.EmailAddress = $EmailAddress      # メールアドレス
$operators.NetSendAddress = $NetSendAddress  # NetSendアドレス
$operators.PagerAddress = $PagerAddress      # ページャーアドレス
$operators.PagerDays = $Interval             # ページャー通知曜日（ビットマスク）
$operators.SaturdayPagerStartTime = $SaturdayStartTime
$operators.SaturdayPagerEndTime = $SaturdayEndTime
$operators.SundayPagerStartTime = $SundayStartTime
$operators.SundayPagerEndTime = $SundayEndTime
$operators.WeekdayPagerStartTime = $WeekdayStartTime
$operators.WeekdayPagerEndTime = $WeekdayEndTime
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| Operator | 作成するオペレーター名 | パラメータ | Yes |
| EmailAddress | メール通知先アドレス | パラメータ | No (いずれか1つ必須) |
| NetSendAddress | NetSend通知先アドレス | パラメータ | No (いずれか1つ必須) |
| PagerAddress | ページャー通知先アドレス | パラメータ | No (いずれか1つ必須) |
| PagerDay | ページャー通知曜日 | パラメータ | No |
| SaturdayStartTime | 土曜ページャー開始時間 | パラメータ（HHMMSS形式） | No |
| SaturdayEndTime | 土曜ページャー終了時間 | パラメータ（HHMMSS形式） | No |
| SundayStartTime | 日曜ページャー開始時間 | パラメータ（HHMMSS形式） | No |
| SundayEndTime | 日曜ページャー終了時間 | パラメータ（HHMMSS形式） | No |
| WeekdayStartTime | 平日ページャー開始時間 | パラメータ（HHMMSS形式） | No |
| WeekdayEndTime | 平日ページャー終了時間 | パラメータ（HHMMSS形式） | No |
| IsFailsafeOperator | フェールセーフオペレーター設定 | パラメータ | No |
| FailsafeNotificationMethod | フェールセーフ通知方法 | パラメータ（デフォルト: NotifyEmail） | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| コマンド実行 | New-DbaAgentOperator実行 | ShouldProcess確認後 | オペレーター作成完了時に出力 |
| パイプライン入力 | InputObject（SMO Server）受信 | ValueFromPipeline | Connect-DbaInstanceからのパイプ入力 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 通知先未指定 | EmailAddress, NetSendAddress, PagerAddressのいずれも指定されていない場合 |
| 既存オペレーター | 同名オペレーターが存在し、-Forceが指定されていない場合 |
| WhatIf指定時 | -WhatIfパラメータ指定時は実際の作成は行わない |
| Confirm拒否時 | -Confirmで確認を求められた際にユーザーが拒否した場合 |
| AGリスナー経由 | 可用性グループリスナー経由で接続した場合（エラー） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[コマンド実行] --> B{通知先指定あり?}
    B -->|No| C[Stop-Function: 通知先必須]
    B -->|Yes| D[PagerDay計算]
    D --> E{ページャー時間検証}
    E -->|NG| F[Stop-Function: 時間形式エラー]
    E -->|OK| G[時間形式変換 HH:MM:SS]
    G --> H[SqlInstanceループ]
    H --> I[Connect-DbaInstance]
    I --> J{既存オペレーター確認}
    J -->|存在 & Force=false| K[スキップ]
    J -->|存在 & Force=true| L{フェールセーフ?}
    L -->|Yes| M[スキップ]
    L -->|No| N[既存をDrop]
    J -->|存在しない| O[新規作成処理]
    N --> O
    O --> P[SMO Operator作成]
    P --> Q[プロパティ設定]
    Q --> R[Create実行]
    R --> S{IsFailsafeOperator?}
    S -->|Yes| T[AlertSystem設定]
    S -->|No| U[Get-DbaAgentOperator]
    T --> U
    U --> V[出力]
    V --> H
    K --> H
    M --> H
    H -->|完了| W[終了]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| msdb.dbo.sysoperators | 既存オペレーター確認 | SMO経由でアクセス |
| msdb.dbo.sysalerts_view | フェールセーフオペレーター確認 | AlertSystem経由 |

### テーブル別参照項目詳細

#### msdb.dbo.sysoperators

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| name | 重複確認 | 指定オペレーター名と比較 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| msdb.dbo.sysoperators | INSERT | 新規オペレーターの作成 |
| msdb.dbo.sysalerts_view | UPDATE | フェールセーフオペレーター設定時 |

#### 新規オペレーター作成時

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | name | $Operator | オペレーター名 |
| INSERT | email_address | $EmailAddress | メールアドレス |
| INSERT | netsend_address | $NetSendAddress | NetSendアドレス |
| INSERT | pager_address | $PagerAddress | ページャーアドレス |
| INSERT | pager_days | $Interval | ページャー曜日ビットマスク |
| INSERT | saturday_pager_start/end_time | 時間値 | 土曜ページャー時間 |
| INSERT | sunday_pager_start/end_time | 時間値 | 日曜ページャー時間 |
| INSERT | weekday_pager_start/end_time | 時間値 | 平日ページャー時間 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 通知先未指定 | EmailAddress, NetSendAddress, PagerAddressのいずれも未指定 | いずれか1つ以上を指定 |
| 時間形式エラー | ページャー時間がHHMMSS形式でない | 000000-235959の範囲で指定 |
| 既存オペレーター | 同名オペレーターが存在 | -Forceを使用するか別名を指定 |
| AGリスナー | 可用性グループリスナー経由の接続 | プライマリレプリカに直接接続 |
| 接続エラー | SQL Serverインスタンスに接続できない | 接続情報を確認し再試行 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（自動リトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A（-Forceで既存削除・再作成が可能） |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（任意のタイミングで実行可能）

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

- SQL Serverインスタンスへのsysadmin権限が必要
- SqlCredentialパラメータを使用して安全に認証情報を渡すことが可能
- SupportsShouldProcessが有効で、ConfirmImpactはMediumに設定
- 可用性グループリスナー経由の操作は禁止（インスタンスレベルの操作のため）

## 備考

- PagerDayパラメータはビットマスクで内部管理：Sunday=1, Monday=2, Tuesday=4, Wednesday=8, Thursday=16, Friday=32, Saturday=64, Weekdays=62, Weekend=65, EveryDay=127
- ページャー時間はHHMMSS形式で指定し、内部でHH:MM:SS形式に変換される
- -Forceパラメータを使用すると、既存オペレーターを削除して再作成（ただしフェールセーフオペレーターは保護）
- IsFailsafeOperatorを指定すると、インスタンスのフェールセーフオペレーターとして設定される
- 作成完了後、Get-DbaAgentOperatorを内部呼び出しして結果を出力

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、出力されるSMOオペレーターオブジェクトとパラメータの構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | New-DbaAgentOperator.ps1 | `public/New-DbaAgentOperator.ps1` | 101-131行目の.OUTPUTSセクションで出力構造を確認 |
| 1-2 | New-DbaAgentOperator.ps1 | `public/New-DbaAgentOperator.ps1` | 148-170行目でパラメータ定義を確認 |

**読解のコツ**: PagerDayパラメータはValidateSetで限定された値のみ受け付け、内部でビットマスク値に変換されます（186-209行目）。

#### Step 2: エントリーポイントを理解する

処理の起点となるfunction定義とパラメータバリデーションを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | New-DbaAgentOperator.ps1 | `public/New-DbaAgentOperator.ps1` | 147行目（CmdletBinding）から処理開始 |
| 2-2 | New-DbaAgentOperator.ps1 | `public/New-DbaAgentOperator.ps1` | 176-180行目で通知先必須チェック |

**主要処理フロー**:
1. **172-174行目**: beginブロックでForce時のConfirmPreference設定
2. **176-180行目**: 通知先（Email/NetSend/Pager）の必須チェック
3. **182-209行目**: PagerDay値からビットマスクへの変換

#### Step 3: ページャー時間の検証と変換を理解する

ページャー時間パラメータの検証と形式変換ロジックを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | New-DbaAgentOperator.ps1 | `public/New-DbaAgentOperator.ps1` | 211行目で時間形式の正規表現定義 |
| 3-2 | New-DbaAgentOperator.ps1 | `public/New-DbaAgentOperator.ps1` | 213-289行目で曜日別時間検証 |
| 3-3 | New-DbaAgentOperator.ps1 | `public/New-DbaAgentOperator.ps1` | 296-316行目で時間形式変換（HH:MM:SS） |

**主要処理フロー**:
- **211行目**: 正規表現 `^(?:(?:([01]?\d|2[0-3]))?([0-5]?\d))?([0-5]?\d)$`
- **297-302行目**: Saturday時間にコロンを挿入
- **304-309行目**: Sunday時間にコロンを挿入
- **311-316行目**: Weekday時間にコロンを挿入

#### Step 4: オペレーター作成処理を理解する

既存オペレーターの確認、削除、新規作成のロジックを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | New-DbaAgentOperator.ps1 | `public/New-DbaAgentOperator.ps1` | 326-350行目で既存オペレーター処理 |
| 4-2 | New-DbaAgentOperator.ps1 | `public/New-DbaAgentOperator.ps1` | 352-420行目でオペレーター作成 |

**主要処理フロー**:
- **329行目**: Get-DbaAgentOperatorで既存確認
- **336-339行目**: フェールセーフオペレーターの保護
- **341-348行目**: -Force時の既存オペレーター削除
- **357行目**: SMO Operatorオブジェクト作成
- **367-405行目**: プロパティ設定
- **407行目**: Create()メソッド呼び出し
- **409-413行目**: フェールセーフオペレーター設定
- **416行目**: Get-DbaAgentOperatorで結果取得

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

```
New-DbaAgentOperator
    |
    +-- [beginブロック]
    |       +-- Force時のConfirmPreference設定
    |
    +-- [processブロック]
            +-- 通知先必須チェック
            +-- PagerDay → ビットマスク変換
            +-- ページャー時間検証（正規表現）
            +-- 時間形式変換（HHMMSS → HH:MM:SS）
            +-- foreach ($instance in $SqlInstance)
            |       +-- Connect-DbaInstance
            |
            +-- foreach ($server in $InputObject)
                    |
                    +-- Get-DbaAgentOperator (既存確認)
                    |
                    +-- 既存時の処理分岐
                    |       +-- Force=false → スキップ
                    |       +-- Force=true & フェールセーフ → スキップ
                    |       +-- Force=true & 非フェールセーフ → Drop()
                    |
                    +-- New-Object SMO.Agent.Operator
                    |       +-- プロパティ設定
                    |       +-- Create()
                    |
                    +-- IsFailsafeOperator時
                    |       +-- AlertSystem設定
                    |       +-- Alter()
                    |
                    +-- Get-DbaAgentOperator (結果取得)
```

### データフロー図

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

SqlInstance[] ──┬──────────────> Connect-DbaInstance ─────┐
                |                                         |
InputObject ────┘                                         |
                                                          v
Operator (名前) ─────────────────────────────────────────> 既存確認
EmailAddress ────┐                                        |
NetSendAddress ──┼─────────────────────────────> SMO Operator作成
PagerAddress ────┘                                        |
                                                          v
PagerDay ────────────────> ビットマスク変換 ────> PagerDays設定
                                                          |
SaturdayStartTime ──┐                                     |
SaturdayEndTime ────┤                                     |
SundayStartTime ────┼─> 時間検証 + 形式変換 ───> ページャー時間設定
SundayEndTime ──────┤                                     |
WeekdayStartTime ───┤                                     |
WeekdayEndTime ─────┘                                     |
                                                          v
IsFailsafeOperator ─────────────────────────────> AlertSystem設定
FailsafeNotificationMethod ─────────────────────────────> |
                                                          v
                                            Get-DbaAgentOperator ──> SMO Operator出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| New-DbaAgentOperator.ps1 | `public/New-DbaAgentOperator.ps1` | ソース | オペレーター作成の本体 |
| Get-DbaAgentOperator.ps1 | `public/Get-DbaAgentOperator.ps1` | ソース | オペレーター取得（結果確認用） |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続 |
| Stop-Function.ps1 | `internal/functions/Stop-Function.ps1` | ソース | エラーハンドリング共通関数 |
| Write-Message.ps1 | `internal/functions/Write-Message.ps1` | ソース | ログ出力共通関数 |
| Set-DbaAgentOperator.ps1 | `public/Set-DbaAgentOperator.ps1` | ソース | オペレーター更新（関連コマンド） |
| Remove-DbaAgentOperator.ps1 | `public/Remove-DbaAgentOperator.ps1` | ソース | オペレーター削除（関連コマンド） |
