Skip to content

Commit 387c2eb

Browse files
committed
[auto] Add new API to install the Pulumi CLI from the Automation API
1 parent a5f3d6c commit 387c2eb

10 files changed

+405
-84
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
component: sdk/auto
2+
kind: Improvements
3+
body: Add new API to install the Pulumi CLI from the Automation API
4+
time: 2024-01-25T13:32:17.304538+01:00
5+
custom:
6+
PR: "226"

sdk/Pulumi.Automation.Tests/LocalPulumiCmdTests.cs

+127-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
using System;
44
using System.Collections.Generic;
5+
using System.IO;
56
using System.Linq;
6-
using System.Text.RegularExpressions;
7+
using System.Runtime.InteropServices;
78
using System.Threading.Tasks;
89
using Pulumi.Automation.Commands;
10+
using Semver;
911
using Xunit;
1012

1113
namespace Pulumi.Automation.Tests
@@ -15,7 +17,7 @@ public class LocalPulumiCmdTests
1517
[Fact]
1618
public async Task CheckVersionCommand()
1719
{
18-
var localCmd = new LocalPulumiCmd();
20+
var localCmd = await LocalPulumiCmd.CreateAsync();
1921
var extraEnv = new Dictionary<string, string?>();
2022
var args = new[] { "version" };
2123

@@ -57,6 +59,129 @@ private List<string> Lines(string s)
5759
.Select(x => x.Trim())
5860
.ToList();
5961
}
62+
63+
[Fact]
64+
public async Task InstallDefaultRoot()
65+
{
66+
var requestedVersion = new SemVersion(3, 102, 0);
67+
await LocalPulumiCmd.Install(new LocalPulumiCmdOptions { Version = requestedVersion });
68+
var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
69+
var pulumiBin = Path.Combine(home, ".pulumi", "versions", requestedVersion.ToString(), "bin", "pulumi");
70+
Assert.True(File.Exists(pulumiBin));
71+
}
72+
73+
[Fact]
74+
public async Task InstallTwice()
75+
{
76+
var tempDir = Path.Combine(Path.GetTempPath(), "automation-test-" + Guid.NewGuid().ToString());
77+
Directory.CreateDirectory(tempDir);
78+
try
79+
{
80+
var requestedVersion = new SemVersion(3, 102, 0);
81+
await LocalPulumiCmd.Install(new LocalPulumiCmdOptions { Version = requestedVersion, Root = tempDir });
82+
var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
83+
var pulumiBin = Path.Combine(home, ".pulumi", "versions", requestedVersion.ToString(), "bin", "pulumi");
84+
FileInfo fi1 = new FileInfo(pulumiBin);
85+
var t1 = fi1.CreationTime;
86+
// Install again with the same options
87+
await LocalPulumiCmd.Install(new LocalPulumiCmdOptions { Version = requestedVersion, Root = tempDir });
88+
FileInfo fi2 = new FileInfo(pulumiBin);
89+
var t2 = fi2.CreationTime;
90+
Assert.Equal(t1, t2);
91+
}
92+
finally
93+
{
94+
Directory.Delete(tempDir, true);
95+
}
96+
97+
}
98+
99+
[Fact]
100+
public async Task VersionCheck()
101+
{
102+
var dirPath = Path.Combine(Path.GetTempPath(), "automation-test-" + Guid.NewGuid().ToString());
103+
var dir = Directory.CreateDirectory(dirPath);
104+
try
105+
{
106+
// Install an old version
107+
var installed_version = new SemVersion(3, 99, 0);
108+
await LocalPulumiCmd.Install(new LocalPulumiCmdOptions { Version = installed_version, Root = dirPath });
109+
110+
// Try to create a command with a more recent version
111+
var requested_version = new SemVersion(3, 102, 0);
112+
await Assert.ThrowsAsync<InvalidOperationException>(() => LocalPulumiCmd.CreateAsync(new LocalPulumiCmdOptions
113+
{
114+
Version = requested_version,
115+
Root = dirPath
116+
}));
117+
118+
// Opting out of the version check works
119+
await LocalPulumiCmd.CreateAsync(new LocalPulumiCmdOptions
120+
{
121+
Version = requested_version,
122+
Root = dirPath,
123+
SkipVersionCheck = true
124+
});
125+
}
126+
finally
127+
{
128+
dir.Delete(true);
129+
}
130+
}
131+
132+
[Fact]
133+
public void PulumiEnvironment()
134+
{
135+
var env = new Dictionary<string, string?>{
136+
{"PATH", "/usr/bin"}
137+
};
138+
var newEnv = LocalPulumiCmd.PulumiEnvironment(env, "pulumi", false);
139+
Assert.Equal("/usr/bin", newEnv["PATH"]);
140+
141+
env = new Dictionary<string, string?>{
142+
{"PATH", "/usr/bin"}
143+
};
144+
newEnv = LocalPulumiCmd.PulumiEnvironment(env, "/some/install/root/bin/pulumi", false);
145+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
146+
{
147+
Assert.Equal("/some/install/root/bin;/usr/bin", newEnv["PATH"]);
148+
}
149+
else
150+
{
151+
Assert.Equal("/some/install/root/bin:/usr/bin", newEnv["PATH"]);
152+
}
153+
}
154+
155+
[Theory]
156+
[InlineData("100.0.0", true, false)]
157+
[InlineData("1.0.0", true, false)]
158+
[InlineData("2.22.0", false, false)]
159+
[InlineData("2.1.0", true, false)]
160+
[InlineData("2.21.2", false, false)]
161+
[InlineData("2.21.1", false, false)]
162+
[InlineData("2.21.0", true, false)]
163+
// Note that prerelease < release so this case should error
164+
[InlineData("2.21.1-alpha.1234", true, false)]
165+
[InlineData("2.20.0", false, true)]
166+
[InlineData("2.22.0", false, true)]
167+
// Invalid version check
168+
[InlineData("invalid", false, true)]
169+
[InlineData("invalid", true, false)]
170+
public void ValidVersionTheory(string currentVersion, bool errorExpected, bool optOut)
171+
{
172+
var testMinVersion = new SemVersion(2, 21, 1);
173+
174+
if (errorExpected)
175+
{
176+
void ValidatePulumiVersion() => LocalPulumiCmd.ParseAndValidatePulumiVersion(testMinVersion, currentVersion, optOut);
177+
Assert.Throws<InvalidOperationException>(ValidatePulumiVersion);
178+
}
179+
else
180+
{
181+
LocalPulumiCmd.ParseAndValidatePulumiVersion(testMinVersion, currentVersion, optOut);
182+
}
183+
}
184+
60185
}
61186

62187
}

sdk/Pulumi.Automation.Tests/LocalWorkspaceTests.cs

-32
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,13 @@
1414
using Pulumi.Automation.Commands.Exceptions;
1515
using Pulumi.Automation.Events;
1616
using Pulumi.Automation.Exceptions;
17-
using Semver;
1817
using Serilog;
1918
using Serilog.Extensions.Logging;
2019
using Xunit;
2120
using Xunit.Abstractions;
2221
using ILogger = Microsoft.Extensions.Logging.ILogger;
2322

2423
using static Pulumi.Automation.Tests.Utility;
25-
using Xunit.Sdk;
2624

2725
namespace Pulumi.Automation.Tests
2826
{
@@ -1682,36 +1680,6 @@ public async Task PulumiVersionTest()
16821680
Assert.Matches("(\\d+\\.)(\\d+\\.)(\\d+)(-.*)?", workspace.PulumiVersion);
16831681
}
16841682

1685-
[Theory]
1686-
[InlineData("100.0.0", true, false)]
1687-
[InlineData("1.0.0", true, false)]
1688-
[InlineData("2.22.0", false, false)]
1689-
[InlineData("2.1.0", true, false)]
1690-
[InlineData("2.21.2", false, false)]
1691-
[InlineData("2.21.1", false, false)]
1692-
[InlineData("2.21.0", true, false)]
1693-
// Note that prerelease < release so this case should error
1694-
[InlineData("2.21.1-alpha.1234", true, false)]
1695-
[InlineData("2.20.0", false, true)]
1696-
[InlineData("2.22.0", false, true)]
1697-
// Invalid version check
1698-
[InlineData("invalid", false, true)]
1699-
[InlineData("invalid", true, false)]
1700-
public void ValidVersionTheory(string currentVersion, bool errorExpected, bool optOut)
1701-
{
1702-
var testMinVersion = new SemVersion(2, 21, 1);
1703-
1704-
if (errorExpected)
1705-
{
1706-
void ValidatePulumiVersion() => LocalWorkspace.ParseAndValidatePulumiVersion(testMinVersion, currentVersion, optOut);
1707-
Assert.Throws<InvalidOperationException>(ValidatePulumiVersion);
1708-
}
1709-
else
1710-
{
1711-
LocalWorkspace.ParseAndValidatePulumiVersion(testMinVersion, currentVersion, optOut);
1712-
}
1713-
}
1714-
17151683
[Fact]
17161684
public async Task RespectsProjectSettingsTest()
17171685
{

sdk/Pulumi.Automation/Commands/CommandResult.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Pulumi.Automation.Commands
66
{
7-
internal class CommandResult
7+
public class CommandResult
88
{
99
public int Code { get; }
1010

sdk/Pulumi.Automation/Commands/IPulumiCmd.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
using System.Threading;
66
using System.Threading.Tasks;
77
using Pulumi.Automation.Events;
8+
using Semver;
89

910
namespace Pulumi.Automation.Commands
1011
{
11-
internal interface IPulumiCmd
12+
public interface IPulumiCmd
1213
{
14+
SemVersion? Version { get; }
15+
1316
Task<CommandResult> RunAsync(
1417
IList<string> args,
1518
string workingDir,

0 commit comments

Comments
 (0)