Home > other >  Is it possible to have two "ServiceManifests" for a single ServiceManifest.xml file
Is it possible to have two "ServiceManifests" for a single ServiceManifest.xml file

Time:12-16

I was wondering if anyone may be able to assist with some questions I have regarding Azure Service Fabric's ServiceManifest.xml and ApplicationManifest.xml files.

Background

I am working with a multi service application in C# that relies on Azure Service Fabric's technology. We use an ApplicationManifest.xml file for our application at large, and a ServiceManifest.xml file for each individual service. Our ServiceManifest follows the following template:

<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="MyServiceName.ConfigurationServicePkg"
                 Version="1.0.0"
                 xmlns="http://schemas.microsoft.com/2011/01/fabric"
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ServiceTypes>
    <!-- This is the name of your ServiceType. 
         This name must match the string used in RegisterServiceType call in Program.cs. -->
    <StatelessServiceType ServiceTypeName="MyServiceName.Configuration" >
     <PlacementConstraints>requestManagerAllowed==true</PlacementConstraints>
     </StatelessServiceType>
  </ServiceTypes>

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <ExeHost>
        <Program>MyCompanyName.MyServiceName.Configuration.exe</Program>
        <WorkingFolder>CodePackage</WorkingFolder>
      </ExeHost>
    </EntryPoint>
    <EnvironmentVariables>
      <EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value=""/>
    </EnvironmentVariables>
  </CodePackage>

  <!-- Config package is the contents of the Config directoy under PackageRoot that contains an 
       independently-updateable and versioned set of custom configuration settings for your service. -->
  <ConfigPackage Name="Config" Version="1.0.0"/>

</ServiceManifest>

Our services (and solution at large) were recently rebranded for a new environment we must deploy to, while still deploying to the old environment. We have edited all of our .csproj files to have two different assembly names depending on which Build Configuration we are targeting, so that we can build and publish the binaries for both the new and old environments.

For example, we have a Configuration Service in our application. When building using the old build configuration, the configuration service's exe would be named as follows OldCompanyName.OldServiceName.Configuration.exe

When building using the new build configuration, the name changes, and looks like NewCompanyName.NewServiceName.Configuration.exe

Problem

The issue is that we still need to be able to deploy to both the new and old environments. When trying to deploy our services to the new environment, Service Fabric uses the Configuration Service's ServiceManifest.xml to determine it needs to find the OldCompanyName.OldServiceName.Configuration.exe executable as the entry point for that service. However, our solution has to be built using the new build configuration, so all the exe's and dll's are named under the new convention NewCompanyName.NewServiceName.Configuration.exe.

Since it is unable to find the entry point for the service, Service fabric throws the following exception:

The EntryPoint OldCompanyName.OldServiceName.Configuration.exe is not found.\r\nFileName: D:\\..\\..\\AppType\\..\\OldCompanyName.OldServiceName.ConfigurationServicePkg\\ServiceManifest.xml

My Question

Does ServiceManifest.xml support having two separate ServiceManifests depending on which build configuration is being used? As an example, my first thought looked something like this (very rough pseudocode):

<?xml version="1.0" encoding="utf-8"?>
<!-- IF using old build configuration -->
<ServiceManifest Name="OldServiceName.ConfigurationServicePkg"
                 Version="1.0.0"
                 xmlns="http://schemas.microsoft.com/2011/01/fabric"
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ServiceTypes>
    <!-- This is the name of your ServiceType. 
         This name must match the string used in RegisterServiceType call in Program.cs. -->
    <StatelessServiceType ServiceTypeName="OldServiceName.Configuration" >
     <PlacementConstraints>requestManagerAllowed==true</PlacementConstraints>
     </StatelessServiceType>
  </ServiceTypes>

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <ExeHost>
        <Program>OldCompanyName.OldServiceName.Configuration.exe</Program>
        <WorkingFolder>CodePackage</WorkingFolder>
      </ExeHost>
    </EntryPoint>
    <EnvironmentVariables>
      <EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value=""/>
    </EnvironmentVariables>
  </CodePackage>

  <!-- Config package is the contents of the Config directoy under PackageRoot that contains an 
       independently-updateable and versioned set of custom configuration settings for your service. -->
  <ConfigPackage Name="Config" Version="1.0.0"/>

</ServiceManifest>

<!-- If using NEW build configuration -->
<ServiceManifest Name="NewServiceName.ConfigurationServicePkg"
                 Version="1.0.0"
                 xmlns="http://schemas.microsoft.com/2011/01/fabric"
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ServiceTypes>
    <!-- This is the name of your ServiceType. 
         This name must match the string used in RegisterServiceType call in Program.cs. -->
    <StatelessServiceType ServiceTypeName="NewServiceName.Configuration" >
     <PlacementConstraints>requestManagerAllowed==true</PlacementConstraints>
     </StatelessServiceType>
  </ServiceTypes>

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <ExeHost>
        <Program>NewCompanyName.NewServiceName.Configuration.exe</Program>
        <WorkingFolder>CodePackage</WorkingFolder>
      </ExeHost>
    </EntryPoint>
    <EnvironmentVariables>
      <EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value=""/>
    </EnvironmentVariables>
  </CodePackage>

  <!-- Config package is the contents of the Config directoy under PackageRoot that contains an 
       independently-updateable and versioned set of custom configuration settings for your service. -->
  <ConfigPackage Name="Config" Version="1.0.0"/>

</ServiceManifest>

Basically, I just need some way for the existing ServiceManifest.xml files to conditionally target differently named entry points depending on which build configuration is being used (which environment we are deploying to). Any thoughts for how to achieve this?

CodePudding user response:

If you are using a pipeline, (like the pipelines feature Azure DevOps), you can use a tokenizer to replace placeholder strings for different environments using variables or variable groups.

You'd create a service manifest template with delimited placeholders (like this {{key}}), replace them for the specific build you're running (old or new) and build the package after.

The template would look like this:

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <ExeHost>
        <Program>{{companyname}}.Configuration.exe</Program>
        <WorkingFolder>CodePackage</WorkingFolder>
      </ExeHost>
    </EntryPoint>
  </CodePackage>

Create an Azure DevOps variable named 'companyname', with value 'NewCompanyName.NewServiceName'.

After tokenizing, the file would look like this:

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <ExeHost>
        <Program>NewCompanyName.NewServiceName.Configuration.exe</Program>
        <WorkingFolder>CodePackage</WorkingFolder>
      </ExeHost>
    </EntryPoint>
  </CodePackage>
  • Related