PnP プロビジョニング エンジンの紹介

この記事では、2015 年 4 月に OfficeDev PnP プロジェクト内で最初にリリースされ、OfficeDev PnP コア ライブラリのリリース スケジュールに合わせて毎月更新されている、PnP プロビジョニング エンジンについて紹介します。

注:

PnP プロビジョニング フレームワーク & PnP プロビジョニング エンジンは、アクティブなコミュニティがサポートを提供するオープン ソース ソリューションです。 Microsoft からのオープン ソース ツールのサポート SLA はありません。

目標

まず、プロビジョニング エンジンを使用する主な目標から見ていきましょう。 Microsoft Office 365 および Microsoft SharePoint Online の導入により、開発者は Microsoft SharePoint、SharePoint Online、および Office 365 全般のカスタム ソフトウェア ソリューションを作成する新しい方法として、新しいクラウド アドイン モデルを使用できます。 これまで開発者は、完全信頼コード (FTC) ソリューションまたはサンドボックス ソリューションのいずれかで CAML/XML ベースの機能フレームワークを使ってカスタム成果物をプロビジョニングしていましたが、新しいクラウド アドイン モデルでは、「リモート プロビジョニング」手法によって成果物をプロビジョニングできます。 「リモート プロビジョニング」とはどういう意味でしょうか。 機能フレームワークを使用するのではなく、利用可能な API (REST または CSOM) を使用して成果物をプロビジョニングすることを意味します。

では、テスト環境と実稼働環境を使用して成果物をモデル化し、プロビジョニングを行う必要がある場合や、カスタマイズを単に複数の顧客に販売する目的で成果物のプロビジョニングを自動化したい場合はどうでしょうか。 また同様に、顧客志向のサイトやプロジェクト志向のサイトなど、複数のサイト インスタンス間で再利用できるカスタム サイト テンプレートを定義したい場合はどうでしょうか。

新しい PnP プロビジョニング エンジンを使用すると、サイト列、コンテンツ タイプ、リスト定義とインスタンス、ページなどのデザインを構成することにより、Web ブラウザーを介してサイトをモデル化できます。 デザインが完了したら、実行した内容をプロビジョニング テンプレート形式 (XML、JSON、PnP ファイル と呼ばれるコンテナー形式) にエクスポートでき、そのテンプレートを必要に応じてターゲット サイトに適用できます。

では、Microsoft Teams のような他の成果物をプロビジョニングする場合はどうすればよいでしょうか。 Azure AD ユーザーのプロビジョニングもできるのでしょうか。 PnP プロビジョニング エンジンは、これらの処理をユーザーに変わって実行することができます。

2 つの種類のテンプレート

エンジンが理解できるテンプレートには基本的に 2 種類あり、サイト テンプレート (プロビジョニング テンプレートとも呼ばれます) と、それの拡張バージョンであるテナント テンプレートがあります。

エンジンが導入された当時は、利用可能なテンプレートの種類は、サイト テンプレートだけでした。 その数年後、Microsoft では、SharePoint サイトの範囲を超えて成果物をプロビジョニングする機能が特徴の、テナント テンプレートを導入しました。 たとえば、テナント テンプレートを使用すると、Microsoft Teams のチーム、Azure AD ユーザー、サイト デザインやサイト スクリプト、テナントを対象としたテーマなどをプロビジョニングできます。サイト テンプレートとは異なり、テナント テンプレートではいわゆる "シーケンス" をテナント テンプレート内に作成してサイト コレクションを作成することができます。

テナント テンプレートとは簡単に言えば、テナント レベルにプロビジョニングする成果物を含むことができるサイト テンプレートのことです。

サイト テンプレートを作成する

既に述べたように、カスタム プロビジョニング テンプレートを作成する最も簡単な方法は、SharePoint Online で新しいサイト コレクションを作成し、成果物 (サイト列、コンテンツ タイプ、リスト、ページなど) を構成し、その結果をプロビジョニング テンプレートとして保存することです。

カスタム ホーム ページを使用してサンプル サイトを定義したとします。

テンプレート サイトのホーム ページ

カスタム ホーム ページに加えて、標準のイベント リストにイベントをいくつか作成しました。

イベント リストのカスタム イベント

そのサイトをプロビジョニング テンプレートとしてエクスポートするには、OfficeDev PnP コア ライブラリに用意されている PowerShell または CSOM コード (拡張メソッド付き) を使用できます。

PowerShell コマンドレットを使用する

注:

この記事では、PnP PowerShell を使用してプロビジョニング エンジンを操作する方法について説明します。 C# を使用する必要がある場合は、「PnP プロビジョニング エンジンとコア ライブラリ」を参照してください。

注:

PnP PowerShell はオープン ソース ソリューションであり、アクティブなコミュニティでサポートが提供されています。 Microsoft からのオープン ソース ツールのサポート SLA はありません。

SharePoint Online 用または SharePoint 用の PowerShell コマンドレットを使用するには、PnP PowerShell の概要に移動し、SharePoint PnP PowerShell モジュールをインストールします。

Connect-PnPOnline コマンドレットを使用して PowerShell 環境を SharePoint Online に接続したら、次の PowerShell コマンドレット を使用できるようになります。

Get-PnPSiteTemplate -Out "PnP-Provisioning-File.xml"

–Out 引数は、プロビジョニング テンプレートの保存場所をコマンドレットに指示します。

テンプレートの抽出と保存の結果は、コマンドレットで使用した拡張機能 (ファイル) によって異なります (現在、.xml および .pnp がサポートされています)。 テンプレートを XML ファイルとして保存するように選択した場合は、次のような感じに表示されます (注: このテンプレートは不完全で、XML 構造の例に過ぎません)。

注:

テンプレートを抽出するための設定には、さまざまな構成オプションがあります。 これに関する詳細については、「PnP プロビジョニング エンジンの構成」を参照してください。

   <?xml version="1.0"?>
<pnp:Provisioning xmlns:pnp="http://schemas.dev.office.com/PnP/2019/09/ProvisioningSchema">
  <pnp:Preferences Generator="OfficeDevPnP.Core, Version=3.14.1910.1, Culture=neutral, PublicKeyToken=null" />
  <pnp:Templates ID="CONTAINER-TEMPLATE-8F4D883BE25B442FB9F889C351D3EA0B">
    <pnp:ProvisioningTemplate ID="TEMPLATE-8F4D883BE25B442FB9F889C351D3EA0B" Version="1" BaseSiteTemplate="SITEPAGEPUBLISHING#0" Scope="RootSite">
      <pnp:WebSettings RequestAccessEmail="" NoCrawl="false" WelcomePage="SitePages/Home.aspx" SiteLogo="{hosturl}{site}/SiteAssets/__sitelogo___sitelogo_theperspective.png"/>
      <pnp:Navigation AddNewPagesToNavigation="true" CreateFriendlyUrlsForNewPages="true">
        <pnp:CurrentNavigation NavigationType="StructuralLocal">
          <pnp:StructuralNavigation RemoveExistingNodes="true">
            <pnp:NavigationNode Title="Who we are" Url="http://linkless.header/" IsExternal="true"/>
            <pnp:NavigationNode Title="What's happening" Url="http://linkless.header/" IsExternal="true"/>
            <pnp:NavigationNode Title="Find it" Url="http://linkless.header/" IsExternal="true"/>
          </pnp:StructuralNavigation>
        </pnp:CurrentNavigation>
      </pnp:Navigation>
      <pnp:Lists>
        <pnp:ListInstance Title="Events" Description="" DocumentTemplate="" TemplateType="106" Url="Lists/Events" MinorVersionLimit="0" MaxVersionLimit="0" DraftVersionVisibility="0" TemplateFeatureID="00bfea71-ec85-4903-972d-ebe475780106" ContentTypesEnabled="true" EnableFolderCreation="false" DefaultDisplayFormUrl="{site}/Lists/Events/DispForm.aspx" DefaultEditFormUrl="{site}/Lists/Events/EditForm.aspx" DefaultNewFormUrl="{site}/Lists/Events/NewForm.aspx" ImageUrl="/_layouts/15/images/itevent.png?rev=44" IrmExpire="false" IrmReject="false" IsApplicationList="false" ValidationFormula="" ValidationMessage="">
        </pnp:ListInstance>
        <pnp:DataRows KeyColumn="Title" UpdateBehavior="Overwrite">
          <pnp:DataRow>
            <pnp:DataValue FieldName="Title">Thanksgiving</pnp:DataValue>
            <pnp:DataValue FieldName="fAllDayEvent">true</pnp:DataValue>
            <pnp:DataValue FieldName="EventDate">2019-11-28 00:00:00</pnp:DataValue>
            <pnp:DataValue FieldName="EndDate">2019-11-28 23:59:00</pnp:DataValue>
          </pnp:DataRow>
          <pnp:DataRow>
            <pnp:DataValue FieldName="Title">In the design lab with Carlos Slattery</pnp:DataValue>
            <pnp:DataValue FieldName="Location">Contoso HQ</pnp:DataValue>
            <pnp:DataValue FieldName="fAllDayEvent">false</pnp:DataValue>
            <pnp:DataValue FieldName="EventDate">2020-01-02 10:00:00</pnp:DataValue>
            <pnp:DataValue FieldName="EndDate">2020-01-02 12:00:00</pnp:DataValue>
          </pnp:DataRow>
        </pnp:DataRows>
      </pnp:Lists>
      <pnp:ClientSidePages>
        <pnp:ClientSidePage PromoteAsNewsArticle="false" PromoteAsTemplate="false" Overwrite="true" Layout="Home" EnableComments="false" Title="Home" ThumbnailUrl="" PageName="Home.aspx" LCID="0">
          <pnp:Header Type="Default" LayoutType="FullWidthImage" TextAlignment="Center" ShowTopicHeader="false" ShowPublishDate="false" TopicHeader="" AlternativeText="" Authors="[]" AuthorByLine="[]" AuthorByLineId="-1" />
          <pnp:Sections>
            <pnp:Section Order="1" Type="OneColumnVerticalSection" VerticalSectionEmphasis="Soft">
              <pnp:Controls>
                <pnp:CanvasControl WebPartType="News" JsonControlData="{&quot;id&quot;: &quot;8c88f208-6c77-4bdb-86a0-0c47b4316588&quot;, &quot;instanceId&quot;: &quot;1ac6db3e-eb95-4d5d-a991-28ee34772313&quot;, ..." ControlId="8c88f208-6c77-4bdb-86a0-0c47b4316588" Order="1" Column="1" />
                <pnp:CanvasControl WebPartType="News" JsonControlData="{&quot;id&quot;: &quot;8c88f208-6c77-4bdb-86a0-0c47b4316588&quot;, &quot;instanceId&quot;: &quot;e5fc83c0-3350-4eea-9606-6627646a0a4b&quot;, &quot;title&quot;: &quot;News&quot;, &quot;description&quot;: &quot;..." ControlId="8c88f208-6c77-4bdb-86a0-0c47b4316588" Order="2" Column="1" />
                <pnp:CanvasControl WebPartType="Custom" JsonControlData="{&quot;id&quot;: &quot;868ac3c3-cad7-4bd6-9a1c-14dc5cc8e823&quot;, &quot;instanceId&quot;: &quot;c1524d29-ab2a-44a3-809e-c01c3762c4ee&quot;, &quot;title&quot;: &quot;Weather&quot;, &quot;description&quot;:..." ControlId="868ac3c3-cad7-4bd6-9a1c-14dc5cc8e823" Order="1" Column="2" />
              </pnp:Controls>
            </pnp:Section>
            <pnp:Section Order="2" Type="OneColumn">
              <pnp:Controls>
                <pnp:CanvasControl WebPartType="CallToAction" JsonControlData="{&quot;id&quot;: &quot;df8e44e7-edd5-46d5-90da-aca1539313b8&quot;, &quot;instanceId&quot;: &quot;b022816d-c9de-4989-aa10-9b44bec4a872&quot;, &quot;title&quot;: &quot;Call to action&quot;, &quot;description&quot;: &quot;Call to action&quot;, &quot;dataVersion&..." Order="1" Column="1" />
              </pnp:Controls>
            </pnp:Section>
            <pnp:Section Order="3" Type="ThreeColumn">
              <pnp:Controls>
                <pnp:CanvasControl WebPartType="Image" JsonControlData="{&quot;id&quot;: &quot;d1d91016-032f-456d-98a4-721247c305e8&quot;, &quot;instanceId&quot;: &quot;984b089c-ca62-4f92-89c0-1ce0e1cb6c03&quot;, &quot;title&quot;: &quot;Image&quot;, &quot;description&quot;: &quot;Image&quot;, &quot;dataVersion&quot;: &quot;1.8&quot;, &quot;..." ControlId="d1d91016-032f-456d-98a4-721247c305e8" Order="1" Column="1" />
                <pnp:CanvasControl WebPartType="Text" ControlId="5755396c-b272-4c0f-8e8d-eb41d218a10e" Order="2" Column="1">
                  <pnp:CanvasControlProperties>
                    <pnp:CanvasControlProperty Key="Text" Value="&lt;p&gt;&lt;span class=&quot;fontColorThemePrimary&quot;&gt;&lt;span class=&quot;fontSizeMediumPlus&quot;&gt;&lt;strong&gt;BREATHTAKING VIDEOS &amp;amp; PHOTOS&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;..." />
                  </pnp:CanvasControlProperties>
                </pnp:CanvasControl>
                <pnp:CanvasControl WebPartType="Button" JsonControlData="{&quot;id&quot;: &quot;0f087d7f-520e-42b7-89c0-496aaf979d58&quot;, &quot;instanceId&quot;: &quot;deb39e2b-11a0-4141-8ac1-1078fe7cc392&quot;, &quot;title&quot;: &quot;..." ControlId="0f087d7f-520e-42b7-89c0-496aaf979d58" Order="3" Column="1" />
                <pnp:CanvasControl WebPartType="Image" JsonControlData="{&quot;id&quot;: &quot;d1d91016-032f-456d-98a4-721247c305e8&quot;, &quot;instanceId&quot;: &quot;e0b59b5b-8a5a-406e-9deb-6e6f9de4bd3b&quot;, &quot;title&quot;: &quot;Image&quot;, ..." ControlId="d1d91016-032f-456d-98a4-721247c305e8" Order="1" Column="2" />
               </pnp:Controls>
            </pnp:Section>
          </pnp:Sections>
        </pnp:ClientSidePage>
      </pnp:ClientSidePages>
      <pnp:Header Layout="Compact" MenuStyle="MegaMenu" BackgroundEmphasis="Strong" />
      <pnp:Footer Enabled="true" RemoveExistingNodes="false" />
    </pnp:ProvisioningTemplate>
  </pnp:Templates>
</pnp:Provisioning>

見てわかる通り、XML 要素については説明は特に必要ないはずです。 例で使用されている XML スキーマは PnP プロビジョニング スキーマのバージョン 201909 を参照しています。これは SharePoint PnP コミュニティと協力して定義されたもので、GitHub 上の PnP-Provisioning-Schema にあります。 同じリポジトリ内に、マークダウン (MD) 自動生成ドキュメントもあります。このドキュメントでは、XML プロビジョニング テンプレートを手動で定義するために使用できる主な要素、タイプ、属性について説明しています。

ProvisioningTemplate を手動で定義する際に、モデル サイトを使用するか、PnP プロビジョニング XSD スキーマに照らして検証する XML ドキュメントを作成するか、あるいは単純に .NET コードを作成してオブジェクトの階層を構築するかは、開発者の意思で選ぶことができます。 これらの方法を混在させることもできます。モデル サイトを使用して、プロビジョニング テンプレートをデザインし、それを XML ファイルとして保存し、メモリ内でカスタマイズをいくらか実行し、同時に ProvisioningTemplate インスタンスをコードで処理することができます。

プロビジョニング テンプレートを適用する

プロビジョニング テンプレートの概要を説明したところで、次は、プロビジョニング テンプレートをターゲット サイトに適用する方法を説明します。

次の図に示すように、SharePoint Online に新しいコミュニケーション サイト コレクションを作成したとします。

新しいサイト コレクションを作成するための SharePoint Online のページ

既定では、サイトは次の図のようになります (Communication サイトの既定のレイアウト)。

新しいターゲットのホーム ページ

PnP PowerShell コマンドレットを使用して、カスタム サイト テンプレートを適用できるようになりました。

Connect-PnPOnline -Url "https://yourtenant.sharepoint.com/sites/targetcommunicationsite"
Invoke-PnPSiteTemplate -Path "PnP-Provisioning-File.xml"

–Path 引数は、コマンドレットにより (Connect-PnPOnline コマンドレットで示される) 現在接続されているサイトに自動的に適用される参照元テンプレート ファイルを参照しています。

注:

サイトテンプレートを適用するには、ターゲット サイトが作成済みで、動作中である必要があると覚えておくと便利です。 テンプレートを使用してサイトをその場で作成する場合は、テナント テンプレートを作成する必要があります。 テナント テンプレートについて詳しくは、以下を参照してください。

テナント テンプレートを適用する

テナント テンプレートはサイト テンプレートによく似ていますが、いくつかの追加の要素が含まれています。その中でもっとも基本的な要素は、"シーケンス" です。

シーケンスは、作成する 1 つまたは複数のサイト コレクションの構成です。 次のテンプレートの抜粋を確認してください。

<pnp:Provisioning xmlns:pnp="http://schemas.dev.office.com/PnP/2019/09/ProvisioningSchema" Author="John White" Generator="Human being" Version="1.0" Description="Home Site" DisplayName="The Perspective">
  <pnp:Sequence ID="sequence">
    <pnp:SiteCollections>
      <pnp:SiteCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="pnp:CommunicationSite" ProvisioningId="MAIN" SiteDesign="Topic" Title="My New Site" Description="" Url="/sites/mynewsite" IsHubSite="false" Owner="user@domain.com">
        <pnp:Templates>
          <pnp:ProvisioningTemplateReference ID="MAIN-TEMPLATE"/>
        </pnp:Templates>
      </pnp:SiteCollection>
    </pnp:SiteCollections>
  </pnp:Sequence>
  <pnp:Templates ID="SITE-TEMPLATES">
    <pnp:ProvisioningTemplate ID="MAIN-TEMPLATE" Version="1" BaseSiteTemplate="SITEPAGEPUBLISHING#0" Scope="RootSite">
      <pnp:Header Layout="Compact" MenuStyle="MegaMenu" BackgroundEmphasis="Strong" />

見てわかるとおり、シーケンスは <pnp:Templates /> 要素と同じレベルで定義されます。 シーケンスには、1 つまたは複数のサイトを含めることができ、サブ サイトを定義することもできます。 各サイトに対しては、サイトを作成した後に、適用する 1 つまたは複数のテンプレートを参照できます。 テンプレートへの参照は、そのテンプレートの ID を使用します。この例では、各テンプレートは同じ XML ファイル内にあります。

テナントにテナント テンプレートを適用するには、次のように入力します。

Connect-PnPOnline https://yourtenant.sharepoint.com
Invoke-PnPTenantTemplate -Path "yourtenanttemplate.xml"

テナント テンプレートの詳細については、「テナント テンプレートの PnP プロビジョニング」を参照してください。

高度なトピック

この記事では基礎的な内容のみを取り扱っていますが、PnP プロビジョニング エンジンを使用する際は、分類法をプロビジョニングすることができ、プロビジョニングの内容 (リスト ID、パラメーター、用語 ID など) に基づいて実行中に置き換えられる変数やトークンも使用できる点を理解しておくことが重要です。 プロビジョニング エンジンは、タイマー ジョブのサービス、プロバイダー ホスト型アドイン、外部サイト、その他から呼び出すことができます。 最後に、PnP プロビジョニング エンジンを使用すると、成果物をテスト/ステージング環境から運用環境に移すことができます。

詳細なトピックについては、その他の記事をご確認ください。

要件とまとめ

PnP のプロビジョニング エンジンをオンプレミスで操作するには、少なくとも SharePoint 2013 の 2015 年 3 月累積更新プログラムをインストールする必要があります。実際、このエンジンが利用しているクライアント側オブジェクト モデルのいくつかの新能は、旧バージョンの製品では使用できません。 SharePoint Online を対象とする場合、この要件は「サービスとしてのソフトウェア (SaaS)」モデルにより自動的に満たされます。

PnP プロビジョニング エンジンを実際に操作して、フィードバックをお送りください。SharePoint アドイン モデルとリモート プロビジョニングの未来をお楽しみください!

関連項目