Skip to content

Commit f02adcd

Browse files
committed
Merge pull request #10 from MRCollective/uninstall-and-latest-tentacle
Tentacle uninstall in OnStop and get the latest Tentacle installer
2 parents ca0550c + 47cba20 commit f02adcd

10 files changed

+121
-19
lines changed

Diff for: AzureWebFarm.OctopusDeploy.Tests/AzureWebFarm.OctopusDeploy.Tests.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
</ItemGroup>
9292
<ItemGroup>
9393
<Compile Include="Infrastructure\OctopusDeployTests.cs" />
94+
<Compile Include="Infrastructure\RegistryEditorTests.cs" />
9495
<Compile Include="Properties\AssemblyInfo.cs" />
9596
<Compile Include="Tools\XdtTests.cs" />
9697
</ItemGroup>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
c:\Install\Tentacle\Tentacle.exe service --instance "Tentacle" --stop --uninstall --console
2+
c:\Install\Tentacle\Tentacle.exe delete-instance --instance "Tentacle" --console
3+
msiexec /uninstall "c:\InstallOctopus.Tentacle.msi" /quiet

Diff for: AzureWebFarm.OctopusDeploy.Tests/Infrastructure/OctopusDeployTests.cs

+21
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,27 @@ public void WhenConfiguringTentacle_ThenTheCorrectCommandsShouldBeSentToTentacle
4747
Approvals.Verify(b.ToString());
4848
}
4949

50+
[Fact]
51+
[UseReporter(typeof(DiffReporter))]
52+
[MethodImpl(MethodImplOptions.NoInlining)]
53+
public void WhenUninstallingTentacle_ThenTheCorrectCommandsShouldBeSentToTentacleExe()
54+
{
55+
var b = new StringBuilder();
56+
_container.Resolve<IProcessRunner>().WhenForAnyArgs(r => r.Run(null, null)).Do(a => b.AppendLine(string.Format("{0} {1}", a[0], a[1])));
57+
58+
_sut.UninstallTentacle();
59+
60+
Approvals.Verify(b.ToString());
61+
}
62+
63+
[Fact]
64+
public void WhenUninstallingTentacle_ThenDeleteTheOctopusRegistryKey()
65+
{
66+
_sut.UninstallTentacle();
67+
68+
_container.Resolve<IRegistryEditor>().Received().DeleteLocalMachineTree("Software", "Octopus");
69+
}
70+
5071
[Fact]
5172
public void WhenDeletingMachine_ThenDeleteTheMachineFromOctopusServer()
5273
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using AzureWebFarm.OctopusDeploy.Infrastructure;
2+
using Microsoft.Win32;
3+
using Shouldly;
4+
using Xunit;
5+
6+
namespace AzureWebFarm.OctopusDeploy.Tests.Infrastructure
7+
{
8+
public class RegistryEditorTests
9+
{
10+
private RegistryEditor _sut = new RegistryEditor();
11+
12+
[Fact]
13+
public void GivenTreeExistsInRegistry_WhenDeletingThatTree_ThenItsNoLongerThere()
14+
{
15+
Registry.LocalMachine.OpenSubKey("Software", true).CreateSubKey("AzureWebFarm.OctopusDeploy").CreateSubKey("Test").SetValue("test", "Hello World!");
16+
17+
_sut.DeleteLocalMachineTree("Software", "AzureWebFarm.OctopusDeploy");
18+
19+
Registry.LocalMachine.OpenSubKey("Software").GetSubKeyNames().ShouldNotContain("AzureWebFarm.OctopusDeploy");
20+
}
21+
22+
[Fact]
23+
public void GivenTreeDoesntExistInRegistry_WhenDeletingThatTree_ThenDontThrowAnException()
24+
{
25+
Registry.LocalMachine.OpenSubKey("Software").GetSubKeyNames().ShouldNotContain("AzureWebFarm.OctopusDeploy");
26+
27+
_sut.DeleteLocalMachineTree("Software", "AzureWebFarm.OctopusDeploy");
28+
}
29+
}
30+
}

Diff for: AzureWebFarm.OctopusDeploy/AzureWebFarm.OctopusDeploy.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
<Compile Include="Infrastructure\IisEnvironment.cs" />
100100
<Compile Include="Infrastructure\OctopusDeploy.cs" />
101101
<Compile Include="Infrastructure\ProcessRunner.cs" />
102+
<Compile Include="Infrastructure\RegistryEditor.cs" />
102103
<Compile Include="Properties\AssemblyInfo.cs" />
103104
<Compile Include="WebFarmRole.cs" />
104105
</ItemGroup>

Diff for: AzureWebFarm.OctopusDeploy/Infrastructure/OctopusDeploy.cs

+23-11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.IO;
44
using System.Linq;
55
using System.Threading;
6+
using Microsoft.Win32;
67
using Microsoft.WindowsAzure.ServiceRuntime;
78
using Octopus.Client;
89
using Octopus.Client.Model;
@@ -13,33 +14,36 @@ namespace AzureWebFarm.OctopusDeploy.Infrastructure
1314
{
1415
internal class OctopusDeploy
1516
{
17+
private const string InstanceArg = "--instance \"Tentacle\"";
1618
private readonly string _machineName;
1719
private readonly ConfigSettings _config;
1820
private readonly IProcessRunner _processRunner;
21+
private readonly IRegistryEditor _registryEditor;
1922
private readonly IOctopusRepository _repository;
23+
private readonly string _tentaclePath;
24+
private readonly string _tentacleInstallPath;
2025

21-
public OctopusDeploy(string machineName, ConfigSettings config, IOctopusRepository repository, IProcessRunner processRunner)
26+
public OctopusDeploy(string machineName, ConfigSettings config, IOctopusRepository repository, IProcessRunner processRunner, IRegistryEditor registryEditor)
2227
{
2328
_machineName = machineName;
2429
_config = config;
2530
_processRunner = processRunner;
31+
_registryEditor = registryEditor;
2632
_repository = repository;
33+
_tentacleInstallPath = _config.TentacleInstallPath;
34+
_tentaclePath = Path.Combine(_tentacleInstallPath, "Tentacle", "Tentacle.exe");
2735
}
2836

2937
public void ConfigureTentacle()
3038
{
31-
const string instanceArg = "--instance \"Tentacle\"";
3239
var tentacleDeploymentsPath = _config.TentacleDeploymentsPath;
33-
var tentacleInstallPath = _config.TentacleInstallPath;
34-
var tentacleDir = Path.Combine(tentacleInstallPath, "Tentacle");
35-
var tentaclePath = Path.Combine(tentacleDir, "Tentacle.exe");
3640

37-
_processRunner.Run(tentaclePath, string.Format("create-instance {0} --config \"{1}\" --console", instanceArg, Path.Combine(tentacleInstallPath, "Tentacle.config")));
38-
_processRunner.Run(tentaclePath, string.Format("new-certificate {0} --console", instanceArg));
39-
_processRunner.Run(tentaclePath, string.Format("configure {0} --home \"{1}\" --console", instanceArg, tentacleDeploymentsPath.Substring(0, tentacleDeploymentsPath.Length - 1)));
40-
_processRunner.Run(tentaclePath, string.Format("configure {0} --app \"{1}\" --console", instanceArg, Path.Combine(tentacleDeploymentsPath, "Applications")));
41-
_processRunner.Run(tentaclePath, string.Format("register-with {0} --server \"{1}\" --environment \"{2}\" --role \"{3}\" --apiKey \"{4}\" --name \"{5}\" --comms-style TentacleActive --force --console", instanceArg, _config.OctopusServer, _config.TentacleEnvironment, _config.TentacleRole, _config.OctopusApiKey, _machineName));
42-
_processRunner.Run(tentaclePath, string.Format("service {0} --install --start --console", instanceArg));
41+
_processRunner.Run(_tentaclePath, string.Format("create-instance {0} --config \"{1}\" --console", InstanceArg, Path.Combine(_tentacleInstallPath, "Tentacle.config")));
42+
_processRunner.Run(_tentaclePath, string.Format("new-certificate {0} --console", InstanceArg));
43+
_processRunner.Run(_tentaclePath, string.Format("configure {0} --home \"{1}\" --console", InstanceArg, tentacleDeploymentsPath.Substring(0, tentacleDeploymentsPath.Length - 1)));
44+
_processRunner.Run(_tentaclePath, string.Format("configure {0} --app \"{1}\" --console", InstanceArg, Path.Combine(tentacleDeploymentsPath, "Applications")));
45+
_processRunner.Run(_tentaclePath, string.Format("register-with {0} --server \"{1}\" --environment \"{2}\" --role \"{3}\" --apiKey \"{4}\" --name \"{5}\" --comms-style TentacleActive --force --console", InstanceArg, _config.OctopusServer, _config.TentacleEnvironment, _config.TentacleRole, _config.OctopusApiKey, _machineName));
46+
_processRunner.Run(_tentaclePath, string.Format("service {0} --install --start --console", InstanceArg));
4347
}
4448

4549
public void DeleteMachine()
@@ -99,5 +103,13 @@ public static IOctopusRepository GetRepository(ConfigSettings config)
99103
{
100104
return new OctopusRepository(new OctopusServerEndpoint(config.OctopusServer, config.OctopusApiKey));
101105
}
106+
107+
public void UninstallTentacle()
108+
{
109+
_processRunner.Run(_tentaclePath, string.Format("service {0} --stop --uninstall --console", InstanceArg));
110+
_processRunner.Run(_tentaclePath, string.Format("delete-instance {0} --console", InstanceArg));
111+
_processRunner.Run("msiexec", string.Format("/uninstall \"{0}{1}\" /quiet", _tentacleInstallPath, "Octopus.Tentacle.msi"));
112+
_registryEditor.DeleteLocalMachineTree("Software", "Octopus");
113+
}
102114
}
103115
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System.Linq;
2+
using Microsoft.Win32;
3+
using Serilog;
4+
5+
namespace AzureWebFarm.OctopusDeploy.Infrastructure
6+
{
7+
public interface IRegistryEditor
8+
{
9+
void DeleteLocalMachineTree(params string[] pathToTree);
10+
}
11+
12+
class RegistryEditor : IRegistryEditor
13+
{
14+
public void DeleteLocalMachineTree(params string[] pathToTree)
15+
{
16+
var keyToDelete = pathToTree[pathToTree.Length - 1];
17+
var currentNode = Registry.LocalMachine;
18+
19+
for (var i = 0; i < pathToTree.Length - 1; i++)
20+
{
21+
currentNode = currentNode.OpenSubKey(pathToTree[i], true);
22+
if (currentNode == null)
23+
{
24+
Log.Debug("Couldn't find HKLM:" + string.Join("/", pathToTree));
25+
return;
26+
}
27+
}
28+
29+
if (currentNode.GetSubKeyNames().Contains(keyToDelete))
30+
currentNode.DeleteSubKeyTree(keyToDelete);
31+
}
32+
}
33+
}

Diff for: AzureWebFarm.OctopusDeploy/WebFarmRole.cs

+7-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ namespace AzureWebFarm.OctopusDeploy
1111
/// </summary>
1212
public class WebFarmRole
1313
{
14-
private readonly ConfigSettings _config;
1514
private readonly Infrastructure.OctopusDeploy _octopusDeploy;
1615

1716
/// <summary>
@@ -21,14 +20,15 @@ public class WebFarmRole
2120
public WebFarmRole(string machineName = null)
2221
{
2322
Log.Logger = AzureEnvironment.GetAzureLogger();
24-
_config = AzureEnvironment.GetConfigSettings();
23+
var config = AzureEnvironment.GetConfigSettings();
2524

26-
machineName = machineName ?? AzureEnvironment.GetMachineName(_config);
27-
var octopusRepository = Infrastructure.OctopusDeploy.GetRepository(_config);
25+
machineName = machineName ?? AzureEnvironment.GetMachineName(config);
26+
var octopusRepository = Infrastructure.OctopusDeploy.GetRepository(config);
2827
var processRunner = new ProcessRunner();
29-
_octopusDeploy = new Infrastructure.OctopusDeploy(machineName, _config, octopusRepository, processRunner);
28+
var registryEditor = new RegistryEditor();
29+
_octopusDeploy = new Infrastructure.OctopusDeploy(machineName, config, octopusRepository, processRunner, registryEditor);
3030

31-
AzureEnvironment.RequestRecycleIfConfigSettingChanged(_config);
31+
AzureEnvironment.RequestRecycleIfConfigSettingChanged(config);
3232
}
3333

3434
/// <summary>
@@ -74,6 +74,7 @@ public void Run()
7474
/// </summary>
7575
public void OnStop()
7676
{
77+
_octopusDeploy.UninstallTentacle();
7778
_octopusDeploy.DeleteMachine();
7879
IisEnvironment.WaitForAllHttpRequestsToEnd();
7980
}

Diff for: ExampleWebFarm/Startup/startup.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
try
44
{
5-
$TentacleDownloadPath = "http://download.octopusdeploy.com/octopus/Octopus.Tentacle.2.1.3.1223-x64.msi"
5+
$TentacleDownloadPath = "https://octopusdeploy.com/downloads/latest/OctopusTentacle64"
66
$TentacleLocalDebuggingPath = "C:\Octopus.Tentacle.msi"
77
$PathToInstall = $env:PathToInstall
88
$PathToDeployments = $env:PathToDeployments

Diff for: NextVersion.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.0.0
1+
1.1.0

0 commit comments

Comments
 (0)