[PowerShell DSC] Configuration Data を利用して構成と環境データを分離する

# はじめに
PowerShell DSC で Configuration Data を使って構成と環境データを分離します。簡単なサンプルとして IP アドレス、デフォルトゲートウェイ、DNS サーバーを設定する PowerShell DSC Configuration を作成します。

環境

- Windows Server 2016
- PowerShell 5.1

設定

- IP アドレス：192.168.2.11/24
- デフォルトゲートウェイ：192.168.2.254
- DNS サーバー（プライマリ）：192.168.2.1
- DNS サーバー（プライマリ）：192.168.2.2


# モジュールの追加

既定では IP アドレスを設定するリソースのモジュールがないので、追加のモジュールをインストールする必要があります。[PowerShell Team の Github](https://github.com/PowerShell) で探すと大体それっぽいリソースが見つかります。今回は [xNetworking](https://github.com/PowerShell/xNetworking) モジュールを使います。

以下のコマンドを実行して xNetworking をインストールしましょう。

```ps1
Install-Module XNetworking
```

ちなみにインストールされたモジュールは以下のフォルダー配下に配置されます。
C:\Program Files\WindowsPowerShell\Modules\xNetworking\

また、`Get-Package` コマンドでインストールされていることが確認できます。

# Configuration の作成（環境データ分離しない版）

とりあえず何も考えずに Configuration を作成してみます。xNetworking モジュールをインポートして、xIPAddress, xDefaultGatewayAddress, xDNSServerAddress リソースを使います。C:\Configurations\NicConfiguration.ps1 を以下のように作成します。InterfaceAlias は NIC の名前です。`Get-NetAdapater | Select InterfaceAlias` で確認できます。

```ps1:NicConfiguration.ps1
Configuration NicConfiguration {

    Import-DscResource -ModuleName xNetworking

    Node 'localhost'
    {
        xIPAddress IPAddress
        {
            InterfaceAlias = 'Ethernet'
            IPAddress = '192.168.2.11'
            PrefixLength = '24'
            AddressFamily = 'IPv4'
        }

        xDefaultGatewayAddress DefaultGatewayAddress
        {
            InterfaceAlias = 'Ethernet'
            Address = '192.168.2.254'
            AddressFamily = 'IPv4'
        }

        xDNSServerAddress DNSServerAddress
        {
            InterfaceAlias = 'Ethernet'
            Address = '192.168.2.1','192.168.2.2'
            AddressFamily = 'IPv4'
        }
    }
}
```

PowerShell で以下のコマンドを実行して Configuration を適用します。

```ps1
cd C:\Configurations\
. .\NicConfiguration.ps1
NicConfiguration -OutputPath C:\MOF
Start-DscConfiguration -Path C:\MOF -Wait -Verbose
```

以下の通りに IP アドレスが設定されます。

![IPアドレス.png](https://qiita-image-store.s3.amazonaws.com/0/168283/27e24d42-2d06-c03b-62a8-f835be5981c3.png)

# Configurtion から環境データを変数に切り出す

先ほどの Configuration ではサーバー固有のアドレスを直接記述していたので、Configuration を使い回しやすいようにデータを変数に切り出します。

```ps1:NicConfiguration.ps1
Configuration NicConfiguration {

    $InterfaceAlias = 'Ethernet'
    $IPAddress = '192.168.2.11'
    $SubnetMask = '24'
    $DefaultGatewayAddress = '192.168.2.254'
    $DNSServerAddress = '192.168.2.1','192.168.2.2'

    Import-DscResource -ModuleName xNetworking

    Node 'localhost'
    {
        xIPAddress IPAddress
        {
            InterfaceAlias = $InterfaceAlias
            IPAddress = $IPAddress
            PrefixLength = $SubnetMask
            AddressFamily = 'IPv4'
        }

        xDefaultGatewayAddress DefaultGatewayAddress
        {
            InterfaceAlias = $InterfaceAlias
            Address = $DefaultGatewayAddress
            AddressFamily = 'IPv4'
        }

        xDNSServerAddress DNSServerAddress
        {
            InterfaceAlias = $InterfaceAlias
            Address = $DNSServerAddress
            AddressFamily = 'IPv4'
        }
    }
}
```

さっきと同じように実行します。

```ps1
cd C:\Configurations\
. .\NicConfiguration.ps1
NicConfiguration -OutputPath C:\MOF
Start-DscConfiguration -Path C:\MOF -Wait -Verbose
```

結果はもちろん変わりません。

# 環境データを実行時に渡せるように変数をパラメーター化

MOF ファイルの生成時に環境データを指定できるように修正します。

```ps1:NicConfiguration.ps1
Configuration NicConfiguration {

    param(
        [Parameter(Mandatory)][string]$InterfaceAlias,
        [Parameter(Mandatory)][string]$IPAddress,
        [Parameter(Mandatory)][int]$SubnetMask,
        [Parameter(Mandatory)][string]$DefaultGatewayAddress,
        [Parameter(Mandatory)][string[]]$DNSServerAddress
    )

    Import-DscResource -ModuleName xNetworking

    Node 'localhost'
    {
        xIPAddress IPAddress
        {
            InterfaceAlias = $InterfaceAlias
            IPAddress = $IPAddress
            PrefixLength = $SubnetMask
            AddressFamily = 'IPv4'
        }

        xDefaultGatewayAddress DefaultGatewayAddress
        {
            InterfaceAlias = $InterfaceAlias
            Address = $DefaultGatewayAddress
            AddressFamily = 'IPv4'
        }

        xDNSServerAddress DNSServerAddress
        {
            InterfaceAlias = $InterfaceAlias
            Address = $DNSServerAddress
            AddressFamily = 'IPv4'
        }
    }
}
```

MOF 生成時に環境データを渡して実行します。

```ps1
cd C:\Configurations\
. .\NicConfiguration.ps1
NicConfiguration -OutputPath C:\MOF -InterfaceAlias Ethernet -IPAddress 192.168.2.11 -SubnetMask 24 -DefaultGatewayAddress 192.168.2.254 -DNSServerAddress 192.168.2.1,192.168.2.2
Start-DscConfiguration -Path C:\MOF -Wait -Verbose
```

# Configuration Data の利用

最後に環境データを別ファイルに分離するために Configuration Data を利用します。まず、これまで同一ファイル内に記述してきた環境データを、別ファイル「NicConfigurationData.psd1」に切り出します。（Configuration Data の拡張子は psd1）

```ps1:NicConfigurationData.psd1
@{
    AllNodes =
    @(
        @{
            NodeName = 'localhost'
            InterfaceAlias = 'Ethernet'
            IPAddress = '192.168.2.11'
            SubnetMask = 24
            DefaultGatewayAddress = '192.168.2.254'
            DNSServerAddress = ('192.168.2.1','192.168.2.2')
        }
    )
}
```

Configuration Data を使うように Configuration を修正します。

```ps1:NicConfiguration.ps1
Configuration NicConfiguration {

    Import-DscResource -ModuleName xNetworking

    Node $AllNodes.NodeName
    {
        xIPAddress IPAddress
        {
            InterfaceAlias = $Node.InterfaceAlias
            IPAddress = $Node.IPAddress
            PrefixLength = $Node.SubnetMask
            AddressFamily = 'IPv4'
        }

        xDefaultGatewayAddress DefaultGatewayAddress
        {
            InterfaceAlias = $Node.InterfaceAlias
            Address = $Node.defaultGatewayAddress
            AddressFamily = 'IPv4'
        }

        xDNSServerAddress DNSServerAddress
        {
            InterfaceAlias = $Node.InterfaceAlias
            Address = $Node.DNSServerAddress
            AddressFamily = 'IPv4'
        }
    }
}
```

MOF 生成時に Configuration Data を指定して実行します。

```ps1
cd C:\Configurations\
. .\NicConfiguration.ps1
NicConfiguration -OutputPath C:\MOFs -ConfigurationData .\NicConfigurationData.psd1
Start-DscConfiguration -Path C:\MOF -Wait -Verbose
```

# まとめ
環境データを分離することで、共通の Configuratin とサーバーごとに異なるデータを分けて管理することができるので構成管理がしやすくなりますね。