Custom version of Service Fabric app deployment

Hi,

For a variety of reasons I would like to create a custom version of the process that deploys a Service Fabric app. I have read this article (Deploying a package to an Azure Service Fabric cluster - Octopus Deploy), including the section on customizing the deployment process. However, I don’t want to do this via a customized powershell script, but rather from a c# app. How would I access the necessary SF parameters (thumbprint / endpoint) to connect to the cluster and so be able to pass them as command line arguments to my app at deploy time?

I have seen references to a ServiceFabricContext.ps1 in the Calamari project which may have been able to shed more light on this, but the links are dead.

Thanks

Hey there Paul, thanks for reaching out! I want to make sure I understand what it is you’re wanting to do. Are you wanting to call a C# app from DeployToServiceFabric.ps1?

Hi Shawn. I would prefer to completely control the deployment with a C# app. So at the moment your deployment script uses DeployToServiceFabric.ps1 to deploy an SF app. I want to replace that with my C#app to do the deployment, but the piece I’m struggling with is how I get the cluster details through to my app.

On the other hand, I guess I could also customize DeployToServiceFabric.ps1 to just call my C# app with the cluster details (endpoint, thumbprint) if I knew what to pass.

Knowing how to do both options would be good.

Apologies for the tardiness of my response, I had jury duty this morning. I’m unsure how to do the whole with a C# app, however, I suppose you could call the Deployment API to retrieve the values of the non-sensitive variables.

The second way, modifying the DeployToServiceFabric.ps1 method, you would have access to the variables via the $OctopusParameters[] variable collection. This would allow you to call the C# application with the variables supplied by Octopus. For example, if you had a variable named MyVar, you could get the value by doing this

$myOctopusVariable = $OctopusParameters[MyVar]

Does this help?

Hi Shawn. Let’s say we go the 2nd way. From the docs, this is your custom powershell deploy script:

In that file there is a piece of code that does this:

# This global clusterConnection should be set by now, from our ServiceFabricContext.
if (-not $global:clusterConnection) {
    Write-Warning "Service Fabric cluster may not be connected."
    throw
}

So can I assume that the SF connection will have already been established if I supply a substitute script? If so, I think I can get the ConnectionEndpoint as a property from clusterConnection. But what about the certificate thumbprint? Would that be from the Octopus variables collection or somewhere else? It would be helpful to share the powershell file that sets up the connection (ServiceFabricContext.ps1?) if you can.

Ah, I see where you’re going, thanks for clarifying. I’m thinking the file was renamed when refactoring our code and is called AzureServiceFabricContext.ps1 now. This file sets $global:clusterConnection = $clusterConnection which looks like it’s used in DeployAzureServiceFabricApplication.ps1. Is this the file you were looking for?

Regards,

Shawn

It’s getting clearer. In addition to the endpoint which I can get from the global cluster connection, there is this for the secure client certificate connection method which is the one we’re using:

    $ClusterConnectionParameters["ServerCertThumbprint"] = $OctopusFabricServerCertThumbprint
    $ClusterConnectionParameters["X509Credential"] = $true
    $ClusterConnectionParameters["StoreLocation"] = $OctopusFabricCertificateStoreLocation
    $ClusterConnectionParameters["StoreName"] = $OctopusFabricCertificateStoreName
    $ClusterConnectionParameters["FindType"] = $OctopusFabricCertificateFindType

All of those settings are passed into the context script. So my question now is can I access these parameters from the custom deployment script in any way?

At the end of the context script there is this:

Write-Verbose "Invoking target script $OctopusFabricTargetScript with $OctopusFabricTargetScriptParameters parameters."
Invoke-Expression ". `"$OctopusFabricTargetScript`" $OctopusFabricTargetScriptParameters"

Is that the invocation of the custom deployment script? If so, it would also be useful to know what parameters are in $OctopusFabricTargetScriptParameters.

Found this page: Connecting securely with client certificates - Octopus Deploy

Which maps the script parameters to their Octopus variable equivalents:

PowerShell Variable Octopus Variable
$OctopusFabricCertificateFindType Octopus.Action.ServiceFabric.CertificateFindType
$OctopusFabricCertificateStoreLocation Octopus.Action.ServiceFabric.CertificateStoreLocation
$OctopusFabricCertificateStoreName Octopus.Action.ServiceFabric.CertificateStoreName
$OctopusFabricClientCertThumbprint Octopus.Action.ServiceFabric.ClientCertThumbprint
$OctopusFabricServerCertThumbprint Octopus.Action.ServiceFabric.ServerCertThumbprint

Interesting, these variables don’t show up in System Variables documentation nor do they show up when using variable debug options. If you enable the printing of variables and evaluated variables using the debug options, do they show up for you?

I need to get a test project together first, at the moment this is all highly theoretical :slight_smile: I would imagine they’d only show up in the context of a service fabric deployment though, is that where you were looking?

Hey there Paul! I reached out internally to see if I can get some more eyes on this. We’d like to get some more details as to what it is you are trying to accomplish?

Hi Shawn. In summary I’m reworking our internal CI/CD processes and I want to get consistency around the way we deploy our SF apps. We have several use cases: local development machine, integration testing environments (Azure) in our CI pipeline and official Octopus environments such as dev, QA, UAT and production. When I deploy an SF application, I want to deploy it using a C# app that accepts some json config about what the SF cluster is (endpoint, cert thumbprint and whatever else is required) and then carries out the deployment. This will eliminate any inconsistencies about the way we manage deployments across our use cases. It thus means for the Octopus environments, I have to change the deployment process, so instead of using your built-in SF deployment step, I use my custom C# command line app. To do this, I will need access to the cluster details, so it can be written to the json config and supplied to the app to carry out the deployment. Does this make it clearer?

To add to this, the current plan looks like:

  • Create a Nuget package containing the SF app and add a custom version of DeployToServiceFabric.ps1 to the root of the package
  • Use the Octopus deploy SF app step to invoke the deployment passing the above package
  • The custom Powershell script is invoked instead of the usual version and writes a config json file with the cluster connection details obtained from various Octopus variables
  • Configure a subsequent Octopus step which calls the C# app and passes the location of the json config, allowing the app to be deployed

Thanks for that additional information. The engineers are telling me that Calimari sets the PowerShell variables so you should have access to items such as $OctopusFabricCertificateStoreLocation from within a custom DeployToServiceFabric.ps1

Awesome :slight_smile: I’m hoping to get round to Octopus testing next week, so will post some feedback then. Thanks for your help Shawn.