[dotnet] Fix Resharper code issues (#7178)
* Fix resharper code issues for language usage opportunities * Fix resharper code issues for common practices and code improvements * Fix resharper code issues for potential code quality issues * Fix resharper code issues for redundancies in code * Fix xunit test output * Update changelog * Fix resharper code issues for compiler warnings * Fix resharper code issues for inconsistent naming * Add resharper solution settings file * Fix resharper code issues for potential code quality issues * Fix resharper code issues for redundancies in code * Fix resharper code issues for redundancies in symbol declarations
This commit is contained in:
parent
3e170f6f80
commit
3530ba3205
|
@ -1,5 +1,7 @@
|
|||
### Improvements
|
||||
|
||||
- [dotnet] Fix Resharper code issues.
|
||||
[#7178](https://github.com/pulumi/pulumi/pull/7178)
|
||||
|
||||
- [codegen] - Include properties with an underlying type of string on Go provider instances.
|
||||
|
||||
|
|
|
@ -80,8 +80,9 @@ namespace Pulumi.Automation.Tests
|
|||
var program = PulumiFn.Create(() =>
|
||||
{
|
||||
hitSemaphore = true;
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
semaphore.Wait();
|
||||
return new Dictionary<string, object?>()
|
||||
return new Dictionary<string, object?>
|
||||
{
|
||||
["test"] = "doesnt matter",
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using System;
|
||||
using Pulumi.Automation.Events;
|
||||
using Xunit;
|
||||
|
||||
|
@ -37,12 +37,7 @@ namespace Pulumi.Automation.Tests
|
|||
[Fact]
|
||||
public async Task PropagatesUserExceptionsToCaller()
|
||||
{
|
||||
using var fx = new Fixture();
|
||||
|
||||
fx.Action = ev =>
|
||||
{
|
||||
throw new MyException();
|
||||
};
|
||||
using var fx = new Fixture { Action = ev => throw new MyException() };
|
||||
|
||||
await fx.Write("{}");
|
||||
|
||||
|
@ -62,7 +57,7 @@ namespace Pulumi.Automation.Tests
|
|||
|
||||
private class MyException : Exception { }
|
||||
|
||||
private class Fixture : IDisposable
|
||||
private sealed class Fixture : IDisposable
|
||||
{
|
||||
public int EventCounter;
|
||||
public string LogFileName { get; }
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
using Pulumi.Automation.Commands;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Pulumi.Automation.Commands;
|
||||
using Xunit;
|
||||
|
||||
namespace Pulumi.Automation.Tests
|
||||
{
|
||||
|
@ -15,8 +15,8 @@ namespace Pulumi.Automation.Tests
|
|||
public async Task CheckVersionCommand()
|
||||
{
|
||||
var localCmd = new LocalPulumiCmd();
|
||||
IDictionary<string, string?> extraEnv = new Dictionary<string, string?>();
|
||||
IEnumerable<string> args = new string[]{ "version" };
|
||||
var extraEnv = new Dictionary<string, string?>();
|
||||
var args = new[] { "version" };
|
||||
|
||||
var stdoutLines = new List<string>();
|
||||
var stderrLines = new List<string>();
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using Semver;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Pulumi.Automation.Exceptions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Pulumi.Automation.Commands.Exceptions;
|
||||
using Pulumi.Automation.Events;
|
||||
using Pulumi.Automation.Exceptions;
|
||||
using Semver;
|
||||
using Xunit;
|
||||
using System.Collections.Immutable;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Pulumi.Automation.Tests
|
||||
{
|
||||
|
@ -124,7 +125,7 @@ namespace Pulumi.Automation.Tests
|
|||
using var workspace = await LocalWorkspace.CreateAsync(new LocalWorkspaceOptions
|
||||
{
|
||||
ProjectSettings = projectSettings,
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
|
@ -144,7 +145,7 @@ namespace Pulumi.Automation.Tests
|
|||
stacks = await workspace.ListStacksAsync();
|
||||
var newStack = stacks.FirstOrDefault(s => s.Name == stackName);
|
||||
Assert.NotNull(newStack);
|
||||
Assert.True(newStack.IsCurrent);
|
||||
Assert.True(newStack!.IsCurrent);
|
||||
|
||||
await workspace.SelectStackAsync(stackName);
|
||||
await workspace.RemoveStackAsync(stackName);
|
||||
|
@ -166,8 +167,6 @@ namespace Pulumi.Automation.Tests
|
|||
ProjectSettings = projectSettings
|
||||
});
|
||||
|
||||
StackDeployment deployment;
|
||||
|
||||
var stackName = $"{RandomStackName()}";
|
||||
try
|
||||
{
|
||||
|
@ -178,7 +177,7 @@ namespace Pulumi.Automation.Tests
|
|||
Assert.Equal(UpdateState.Succeeded, upResult.Summary.Result);
|
||||
Assert.Equal(3, upResult.Outputs.Count);
|
||||
|
||||
deployment = await workspace.ExportStackAsync(stackName);
|
||||
var deployment = await workspace.ExportStackAsync(stackName);
|
||||
Assert.True(deployment.Version > 0);
|
||||
|
||||
var previewBeforeDestroy = await stack.PreviewAsync();
|
||||
|
@ -214,7 +213,7 @@ namespace Pulumi.Automation.Tests
|
|||
using var workspace = await LocalWorkspace.CreateAsync(new LocalWorkspaceOptions
|
||||
{
|
||||
ProjectSettings = projectSettings,
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
|
@ -223,12 +222,6 @@ namespace Pulumi.Automation.Tests
|
|||
var stackName = $"{RandomStackName()}";
|
||||
var stack = await WorkspaceStack.CreateAsync(stackName, workspace);
|
||||
|
||||
var config = new Dictionary<string, ConfigValue>()
|
||||
{
|
||||
["plain"] = new ConfigValue("abc"),
|
||||
["secret"] = new ConfigValue("def", isSecret: true),
|
||||
};
|
||||
|
||||
var plainKey = NormalizeConfigKey("plain", projectName);
|
||||
var secretKey = NormalizeConfigKey("secret", projectName);
|
||||
|
||||
|
@ -240,7 +233,13 @@ namespace Pulumi.Automation.Tests
|
|||
var values = await stack.GetAllConfigAsync();
|
||||
Assert.Empty(values);
|
||||
|
||||
var config = new Dictionary<string, ConfigValue>
|
||||
{
|
||||
["plain"] = new ConfigValue("abc"),
|
||||
["secret"] = new ConfigValue("def", isSecret: true),
|
||||
};
|
||||
await stack.SetAllConfigAsync(config);
|
||||
|
||||
values = await stack.GetAllConfigAsync();
|
||||
Assert.True(values.TryGetValue(plainKey, out var plainValue));
|
||||
Assert.Equal("abc", plainValue!.Value);
|
||||
|
@ -282,7 +281,7 @@ namespace Pulumi.Automation.Tests
|
|||
using var workspace = await LocalWorkspace.CreateAsync(new LocalWorkspaceOptions
|
||||
{
|
||||
ProjectSettings = projectSettings,
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
|
@ -320,7 +319,7 @@ namespace Pulumi.Automation.Tests
|
|||
using var workspace = await LocalWorkspace.CreateAsync(new LocalWorkspaceOptions
|
||||
{
|
||||
ProjectSettings = projectSettings,
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
|
@ -348,19 +347,19 @@ namespace Pulumi.Automation.Tests
|
|||
var workingDir = ResourcePath(Path.Combine("Data", "testproj"));
|
||||
using var stack = await LocalWorkspace.CreateStackAsync(new LocalProgramArgs(stackName, workingDir)
|
||||
{
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
});
|
||||
|
||||
var config = new Dictionary<string, ConfigValue>()
|
||||
{
|
||||
["bar"] = new ConfigValue("abc"),
|
||||
["buzz"] = new ConfigValue("secret", isSecret: true),
|
||||
};
|
||||
try
|
||||
{
|
||||
var config = new Dictionary<string, ConfigValue>
|
||||
{
|
||||
["bar"] = new ConfigValue("abc"),
|
||||
["buzz"] = new ConfigValue("secret", isSecret: true),
|
||||
};
|
||||
await stack.SetAllConfigAsync(config);
|
||||
|
||||
// pulumi up
|
||||
|
@ -410,7 +409,7 @@ namespace Pulumi.Automation.Tests
|
|||
{
|
||||
var program = PulumiFn.Create(() =>
|
||||
{
|
||||
var config = new Pulumi.Config();
|
||||
var config = new Config();
|
||||
return new Dictionary<string, object?>
|
||||
{
|
||||
["exp_static"] = "foo",
|
||||
|
@ -424,19 +423,19 @@ namespace Pulumi.Automation.Tests
|
|||
var projectName = "inline_node";
|
||||
using var stack = await LocalWorkspace.CreateStackAsync(new InlineProgramArgs(projectName, stackName, program)
|
||||
{
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
});
|
||||
|
||||
var config = new Dictionary<string, ConfigValue>()
|
||||
{
|
||||
["bar"] = new ConfigValue("abc"),
|
||||
["buzz"] = new ConfigValue("secret", isSecret: true),
|
||||
};
|
||||
try
|
||||
{
|
||||
var config = new Dictionary<string, ConfigValue>
|
||||
{
|
||||
["bar"] = new ConfigValue("abc"),
|
||||
["buzz"] = new ConfigValue("secret", isSecret: true),
|
||||
};
|
||||
await stack.SetAllConfigAsync(config);
|
||||
|
||||
// pulumi up
|
||||
|
@ -499,20 +498,19 @@ namespace Pulumi.Automation.Tests
|
|||
var projectName = "inline_node";
|
||||
using var stack = await LocalWorkspace.CreateStackAsync(new InlineProgramArgs(projectName, stackName, program)
|
||||
{
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
});
|
||||
|
||||
var config = new Dictionary<string, ConfigValue>()
|
||||
{
|
||||
["bar"] = new ConfigValue("abc"),
|
||||
["buzz"] = new ConfigValue("secret", isSecret: true),
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var config = new Dictionary<string, ConfigValue>
|
||||
{
|
||||
["bar"] = new ConfigValue("abc"),
|
||||
["buzz"] = new ConfigValue("secret", isSecret: true),
|
||||
};
|
||||
await stack.SetAllConfigAsync(config);
|
||||
|
||||
var initialOutputs = await stack.GetOutputsAsync();
|
||||
|
@ -565,12 +563,10 @@ namespace Pulumi.Automation.Tests
|
|||
public async Task StackReferenceDestroyDiscardsWithTwoInlinePrograms()
|
||||
{
|
||||
var programA = PulumiFn.Create(() =>
|
||||
{
|
||||
return new Dictionary<string, object?>
|
||||
new Dictionary<string, object?>
|
||||
{
|
||||
["exp_static"] = "foo",
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
var programB = PulumiFn.Create(() =>
|
||||
{
|
||||
|
@ -588,7 +584,7 @@ namespace Pulumi.Automation.Tests
|
|||
|
||||
var stackA = await SetupStack(projectName, stackNameA, programA, new Dictionary<string, ConfigValue>());
|
||||
|
||||
var stackB = await SetupStack(projectName, stackNameB, programB, new Dictionary<string, ConfigValue>()
|
||||
var stackB = await SetupStack(projectName, stackNameB, programB, new Dictionary<string, ConfigValue>
|
||||
{
|
||||
["Ref"] = new ConfigValue(FullyQualifiedStackName(_pulumiOrg, projectName, stackNameA)),
|
||||
});
|
||||
|
@ -645,7 +641,7 @@ namespace Pulumi.Automation.Tests
|
|||
{
|
||||
var stack = await LocalWorkspace.CreateStackAsync(new InlineProgramArgs(project, stackName, program)
|
||||
{
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
|
@ -661,18 +657,16 @@ namespace Pulumi.Automation.Tests
|
|||
public async Task OutputStreamAndDelegateIsWritten()
|
||||
{
|
||||
var program = PulumiFn.Create(() =>
|
||||
{
|
||||
return new Dictionary<string, object?>
|
||||
new Dictionary<string, object?>
|
||||
{
|
||||
["test"] = "test",
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
var stackName = $"{RandomStackName()}";
|
||||
var projectName = "inline_output";
|
||||
using var stack = await LocalWorkspace.CreateStackAsync(new InlineProgramArgs(projectName, stackName, program)
|
||||
{
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
|
@ -680,29 +674,27 @@ namespace Pulumi.Automation.Tests
|
|||
|
||||
try
|
||||
{
|
||||
var outputCalled = false;
|
||||
|
||||
// pulumi preview
|
||||
outputCalled = false;
|
||||
var previewResult = await stack.PreviewAsync(new PreviewOptions { OnStandardOutput = (str) => outputCalled = true });
|
||||
var outputCalled = false;
|
||||
var previewResult = await stack.PreviewAsync(new PreviewOptions { OnStandardOutput = str => outputCalled = true });
|
||||
Assert.False(string.IsNullOrEmpty(previewResult.StandardOutput));
|
||||
Assert.True(outputCalled);
|
||||
|
||||
// pulumi up
|
||||
outputCalled = false;
|
||||
var upResult = await stack.UpAsync(new UpOptions { OnStandardOutput = (str) => outputCalled = true });
|
||||
var upResult = await stack.UpAsync(new UpOptions { OnStandardOutput = str => outputCalled = true });
|
||||
Assert.False(string.IsNullOrEmpty(upResult.StandardOutput));
|
||||
Assert.True(outputCalled);
|
||||
|
||||
// pulumi refresh
|
||||
outputCalled = false;
|
||||
var refreshResult = await stack.RefreshAsync(new RefreshOptions { OnStandardOutput = (str) => outputCalled = true });
|
||||
var refreshResult = await stack.RefreshAsync(new RefreshOptions { OnStandardOutput = str => outputCalled = true });
|
||||
Assert.False(string.IsNullOrEmpty(refreshResult.StandardOutput));
|
||||
Assert.True(outputCalled);
|
||||
|
||||
// pulumi destroy
|
||||
outputCalled = false;
|
||||
var destroyResult = await stack.DestroyAsync(new DestroyOptions { OnStandardOutput = (str) => outputCalled = true });
|
||||
var destroyResult = await stack.DestroyAsync(new DestroyOptions { OnStandardOutput = str => outputCalled = true });
|
||||
Assert.False(string.IsNullOrEmpty(destroyResult.StandardOutput));
|
||||
Assert.True(outputCalled);
|
||||
}
|
||||
|
@ -716,17 +708,15 @@ namespace Pulumi.Automation.Tests
|
|||
public async Task HandlesEvents()
|
||||
{
|
||||
var program = PulumiFn.Create(() =>
|
||||
{
|
||||
return new Dictionary<string, object?>
|
||||
new Dictionary<string, object?>
|
||||
{
|
||||
["exp_static"] = "foo",
|
||||
};
|
||||
});
|
||||
});
|
||||
var projectName = "event_test";
|
||||
var stackName = $"inline_events{GetTestSuffix()}";
|
||||
using var stack = await LocalWorkspace.CreateStackAsync(new InlineProgramArgs(projectName, stackName, program)
|
||||
{
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
|
@ -769,7 +759,7 @@ namespace Pulumi.Automation.Tests
|
|||
{
|
||||
var events = new List<EngineEvent>();
|
||||
|
||||
var result = await func(new TOptions() { OnEvent = events.Add }, CancellationToken.None);
|
||||
var result = await func(new TOptions { OnEvent = events.Add }, CancellationToken.None);
|
||||
|
||||
var seenSummaryEvent = events.Any(@event => @event.SummaryEvent != null);
|
||||
var seenCancelEvent = events.Any(@event => @event.CancelEvent != null);
|
||||
|
@ -806,10 +796,10 @@ namespace Pulumi.Automation.Tests
|
|||
config.GetSecretInt32("plainint3");
|
||||
config.RequireSecretInt32("plainint4");
|
||||
|
||||
config.GetObject<System.Text.Json.JsonElement>("plainobj1");
|
||||
config.RequireObject<System.Text.Json.JsonElement>("plainobj2");
|
||||
config.GetSecretObject<System.Text.Json.JsonElement>("plainobj3");
|
||||
config.RequireSecretObject<System.Text.Json.JsonElement>("plainobj4");
|
||||
config.GetObject<JsonElement>("plainobj1");
|
||||
config.RequireObject<JsonElement>("plainobj2");
|
||||
config.GetSecretObject<JsonElement>("plainobj3");
|
||||
config.RequireSecretObject<JsonElement>("plainobj4");
|
||||
|
||||
config.Get("str1");
|
||||
config.Require("str2");
|
||||
|
@ -826,59 +816,59 @@ namespace Pulumi.Automation.Tests
|
|||
config.GetSecretInt32("int3");
|
||||
config.RequireSecretInt32("int4");
|
||||
|
||||
config.GetObject<System.Text.Json.JsonElement>("obj1");
|
||||
config.RequireObject<System.Text.Json.JsonElement>("obj2");
|
||||
config.GetSecretObject<System.Text.Json.JsonElement>("obj3");
|
||||
config.RequireSecretObject<System.Text.Json.JsonElement>("obj4");
|
||||
config.GetObject<JsonElement>("obj1");
|
||||
config.RequireObject<JsonElement>("obj2");
|
||||
config.GetSecretObject<JsonElement>("obj3");
|
||||
config.RequireSecretObject<JsonElement>("obj4");
|
||||
});
|
||||
|
||||
var projectName = "inline_dotnet";
|
||||
var stackName = $"inline_dotnet{GetTestSuffix()}";
|
||||
using var stack = await LocalWorkspace.CreateStackAsync(new InlineProgramArgs(projectName, stackName, program)
|
||||
{
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
});
|
||||
|
||||
var config = new Dictionary<string, ConfigValue>()
|
||||
{
|
||||
{ "plainstr1", new ConfigValue("1") },
|
||||
{ "plainstr2", new ConfigValue("2") },
|
||||
{ "plainstr3", new ConfigValue("3") },
|
||||
{ "plainstr4", new ConfigValue("4") },
|
||||
{ "plainbool1", new ConfigValue("true") },
|
||||
{ "plainbool2", new ConfigValue("true") },
|
||||
{ "plainbool3", new ConfigValue("true") },
|
||||
{ "plainbool4", new ConfigValue("true") },
|
||||
{ "plainint1", new ConfigValue("1") },
|
||||
{ "plainint2", new ConfigValue("2") },
|
||||
{ "plainint3", new ConfigValue("3") },
|
||||
{ "plainint4", new ConfigValue("4") },
|
||||
{ "plainobj1", new ConfigValue("{}") },
|
||||
{ "plainobj2", new ConfigValue("{}") },
|
||||
{ "plainobj3", new ConfigValue("{}") },
|
||||
{ "plainobj4", new ConfigValue("{}") },
|
||||
{ "str1", new ConfigValue("1", isSecret: true) },
|
||||
{ "str2", new ConfigValue("2", isSecret: true) },
|
||||
{ "str3", new ConfigValue("3", isSecret: true) },
|
||||
{ "str4", new ConfigValue("4", isSecret: true) },
|
||||
{ "bool1", new ConfigValue("true", isSecret: true) },
|
||||
{ "bool2", new ConfigValue("true", isSecret: true) },
|
||||
{ "bool3", new ConfigValue("true", isSecret: true) },
|
||||
{ "bool4", new ConfigValue("true", isSecret: true) },
|
||||
{ "int1", new ConfigValue("1", isSecret: true) },
|
||||
{ "int2", new ConfigValue("2", isSecret: true) },
|
||||
{ "int3", new ConfigValue("3", isSecret: true) },
|
||||
{ "int4", new ConfigValue("4", isSecret: true) },
|
||||
{ "obj1", new ConfigValue("{}", isSecret: true) },
|
||||
{ "obj2", new ConfigValue("{}", isSecret: true) },
|
||||
{ "obj3", new ConfigValue("{}", isSecret: true) },
|
||||
{ "obj4", new ConfigValue("{}", isSecret: true) },
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var config = new Dictionary<string, ConfigValue>
|
||||
{
|
||||
{ "plainstr1", new ConfigValue("1") },
|
||||
{ "plainstr2", new ConfigValue("2") },
|
||||
{ "plainstr3", new ConfigValue("3") },
|
||||
{ "plainstr4", new ConfigValue("4") },
|
||||
{ "plainbool1", new ConfigValue("true") },
|
||||
{ "plainbool2", new ConfigValue("true") },
|
||||
{ "plainbool3", new ConfigValue("true") },
|
||||
{ "plainbool4", new ConfigValue("true") },
|
||||
{ "plainint1", new ConfigValue("1") },
|
||||
{ "plainint2", new ConfigValue("2") },
|
||||
{ "plainint3", new ConfigValue("3") },
|
||||
{ "plainint4", new ConfigValue("4") },
|
||||
{ "plainobj1", new ConfigValue("{}") },
|
||||
{ "plainobj2", new ConfigValue("{}") },
|
||||
{ "plainobj3", new ConfigValue("{}") },
|
||||
{ "plainobj4", new ConfigValue("{}") },
|
||||
{ "str1", new ConfigValue("1", isSecret: true) },
|
||||
{ "str2", new ConfigValue("2", isSecret: true) },
|
||||
{ "str3", new ConfigValue("3", isSecret: true) },
|
||||
{ "str4", new ConfigValue("4", isSecret: true) },
|
||||
{ "bool1", new ConfigValue("true", isSecret: true) },
|
||||
{ "bool2", new ConfigValue("true", isSecret: true) },
|
||||
{ "bool3", new ConfigValue("true", isSecret: true) },
|
||||
{ "bool4", new ConfigValue("true", isSecret: true) },
|
||||
{ "int1", new ConfigValue("1", isSecret: true) },
|
||||
{ "int2", new ConfigValue("2", isSecret: true) },
|
||||
{ "int3", new ConfigValue("3", isSecret: true) },
|
||||
{ "int4", new ConfigValue("4", isSecret: true) },
|
||||
{ "obj1", new ConfigValue("{}", isSecret: true) },
|
||||
{ "obj2", new ConfigValue("{}", isSecret: true) },
|
||||
{ "obj3", new ConfigValue("{}", isSecret: true) },
|
||||
{ "obj4", new ConfigValue("{}", isSecret: true) },
|
||||
};
|
||||
await stack.SetAllConfigAsync(config);
|
||||
|
||||
// pulumi preview
|
||||
|
@ -895,7 +885,7 @@ namespace Pulumi.Automation.Tests
|
|||
static async Task<T> RunCommand<T, TOptions>(Func<TOptions, CancellationToken, Task<T>> func, string command)
|
||||
where TOptions : UpdateOptions, new()
|
||||
{
|
||||
var expectedWarnings = new string[]
|
||||
var expectedWarnings = new[]
|
||||
{
|
||||
"Configuration 'inline_dotnet:str1' value is a secret; use `GetSecret` instead of `Get`",
|
||||
"Configuration 'inline_dotnet:str2' value is a secret; use `RequireSecret` instead of `Require`",
|
||||
|
@ -908,7 +898,7 @@ namespace Pulumi.Automation.Tests
|
|||
};
|
||||
|
||||
// These keys should not be in any warning messages.
|
||||
var unexpectedWarnings = new string[]
|
||||
var unexpectedWarnings = new[]
|
||||
{
|
||||
"plainstr1",
|
||||
"plainstr2",
|
||||
|
@ -938,7 +928,7 @@ namespace Pulumi.Automation.Tests
|
|||
|
||||
var events = new List<DiagnosticEvent>();
|
||||
|
||||
var result = await func(new TOptions()
|
||||
var result = await func(new TOptions
|
||||
{
|
||||
OnEvent = @event =>
|
||||
{
|
||||
|
@ -976,7 +966,7 @@ namespace Pulumi.Automation.Tests
|
|||
|
||||
public ValidStack()
|
||||
{
|
||||
var config = new Pulumi.Config();
|
||||
var config = new Config();
|
||||
this.ExpStatic = Output.Create("foo");
|
||||
this.ExpConfig = Output.Create(config.Get("bar")!);
|
||||
this.ExpSecret = config.GetSecret("buzz")!;
|
||||
|
@ -993,19 +983,19 @@ namespace Pulumi.Automation.Tests
|
|||
var projectName = "inline_tstack_node";
|
||||
using var stack = await LocalWorkspace.CreateStackAsync(new InlineProgramArgs(projectName, stackName, program)
|
||||
{
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
});
|
||||
|
||||
var config = new Dictionary<string, ConfigValue>()
|
||||
{
|
||||
["bar"] = new ConfigValue("abc"),
|
||||
["buzz"] = new ConfigValue("secret", isSecret: true),
|
||||
};
|
||||
try
|
||||
{
|
||||
var config = new Dictionary<string, ConfigValue>
|
||||
{
|
||||
["bar"] = new ConfigValue("abc"),
|
||||
["buzz"] = new ConfigValue("secret", isSecret: true),
|
||||
};
|
||||
await stack.SetAllConfigAsync(config);
|
||||
|
||||
// pulumi up
|
||||
|
@ -1053,7 +1043,7 @@ namespace Pulumi.Automation.Tests
|
|||
[Fact]
|
||||
public async Task StackLifecycleInlineProgramWithServiceProvider()
|
||||
{
|
||||
using var provider = new ServiceCollection()
|
||||
await using var provider = new ServiceCollection()
|
||||
.AddTransient<ValidStack>() // must be transient so it is instantiated each time
|
||||
.BuildServiceProvider();
|
||||
|
||||
|
@ -1064,19 +1054,19 @@ namespace Pulumi.Automation.Tests
|
|||
var projectName = "inline_serviceprovider_node";
|
||||
using var stack = await LocalWorkspace.CreateStackAsync(new InlineProgramArgs(projectName, stackName, program)
|
||||
{
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
});
|
||||
|
||||
var config = new Dictionary<string, ConfigValue>()
|
||||
{
|
||||
["bar"] = new ConfigValue("abc"),
|
||||
["buzz"] = new ConfigValue("secret", isSecret: true),
|
||||
};
|
||||
try
|
||||
{
|
||||
var config = new Dictionary<string, ConfigValue>
|
||||
{
|
||||
["bar"] = new ConfigValue("abc"),
|
||||
["buzz"] = new ConfigValue("secret", isSecret: true),
|
||||
};
|
||||
await stack.SetAllConfigAsync(config);
|
||||
|
||||
// pulumi up
|
||||
|
@ -1131,7 +1121,7 @@ namespace Pulumi.Automation.Tests
|
|||
|
||||
using var stack = await LocalWorkspace.CreateStackAsync(new InlineProgramArgs(projectName, stackName, program)
|
||||
{
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
|
@ -1146,7 +1136,7 @@ namespace Pulumi.Automation.Tests
|
|||
() => upTask);
|
||||
}
|
||||
|
||||
private class FileNotFoundStack : Pulumi.Stack
|
||||
private class FileNotFoundStack : Stack
|
||||
{
|
||||
public FileNotFoundStack()
|
||||
{
|
||||
|
@ -1164,7 +1154,7 @@ namespace Pulumi.Automation.Tests
|
|||
|
||||
using var stack = await LocalWorkspace.CreateStackAsync(new InlineProgramArgs(projectName, stackName, program)
|
||||
{
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
|
@ -1182,7 +1172,7 @@ namespace Pulumi.Automation.Tests
|
|||
[Fact]
|
||||
public async Task InlineProgramExceptionPropagatesToCallerWithServiceProvider()
|
||||
{
|
||||
using var provider = new ServiceCollection()
|
||||
await using var provider = new ServiceCollection()
|
||||
.AddTransient<FileNotFoundStack>() // must be transient so it is instantiated each time
|
||||
.BuildServiceProvider();
|
||||
|
||||
|
@ -1193,7 +1183,7 @@ namespace Pulumi.Automation.Tests
|
|||
|
||||
using var stack = await LocalWorkspace.CreateStackAsync(new InlineProgramArgs(projectName, stackName, program)
|
||||
{
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
|
@ -1225,10 +1215,11 @@ namespace Pulumi.Automation.Tests
|
|||
// the semaphore because we want to alternately stutter
|
||||
// programOne and programTwo so we can assert they aren't
|
||||
// touching eachothers instances
|
||||
var config = new Pulumi.Config();
|
||||
var config = new Config();
|
||||
Assert.Equal(projectNameOne, Deployment.Instance.ProjectName);
|
||||
Assert.Equal(stackNameOne, Deployment.Instance.StackName);
|
||||
hasReachedSemaphoreOne = true;
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
semaphoreOne.Wait();
|
||||
Assert.Equal(projectNameOne, Deployment.Instance.ProjectName);
|
||||
Assert.Equal(stackNameOne, Deployment.Instance.StackName);
|
||||
|
@ -1245,10 +1236,11 @@ namespace Pulumi.Automation.Tests
|
|||
|
||||
var programTwo = PulumiFn.Create(() =>
|
||||
{
|
||||
var config = new Pulumi.Config();
|
||||
var config = new Config();
|
||||
Assert.Equal(projectNameTwo, Deployment.Instance.ProjectName);
|
||||
Assert.Equal(stackNameTwo, Deployment.Instance.StackName);
|
||||
hasReachedSemaphoreTwo = true;
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
semaphoreTwo.Wait();
|
||||
Assert.Equal(projectNameTwo, Deployment.Instance.ProjectName);
|
||||
Assert.Equal(stackNameTwo, Deployment.Instance.StackName);
|
||||
|
@ -1262,7 +1254,7 @@ namespace Pulumi.Automation.Tests
|
|||
|
||||
using var stackOne = await LocalWorkspace.CreateStackAsync(new InlineProgramArgs(projectNameOne, stackNameOne, programOne)
|
||||
{
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
|
@ -1270,19 +1262,19 @@ namespace Pulumi.Automation.Tests
|
|||
|
||||
using var stackTwo = await LocalWorkspace.CreateStackAsync(new InlineProgramArgs(projectNameTwo, stackNameTwo, programTwo)
|
||||
{
|
||||
EnvironmentVariables = new Dictionary<string, string?>()
|
||||
EnvironmentVariables = new Dictionary<string, string?>
|
||||
{
|
||||
["PULUMI_CONFIG_PASSPHRASE"] = "test",
|
||||
}
|
||||
});
|
||||
|
||||
await stackOne.SetAllConfigAsync(new Dictionary<string, ConfigValue>()
|
||||
await stackOne.SetAllConfigAsync(new Dictionary<string, ConfigValue>
|
||||
{
|
||||
["bar"] = new ConfigValue("1"),
|
||||
["buzz"] = new ConfigValue("1", isSecret: true),
|
||||
});
|
||||
|
||||
await stackTwo.SetAllConfigAsync(new Dictionary<string, ConfigValue>()
|
||||
await stackTwo.SetAllConfigAsync(new Dictionary<string, ConfigValue>
|
||||
{
|
||||
["bar"] = new ConfigValue("2"),
|
||||
["buzz"] = new ConfigValue("2", isSecret: true),
|
||||
|
@ -1295,7 +1287,7 @@ namespace Pulumi.Automation.Tests
|
|||
await Task.Delay(TimeSpan.FromSeconds(2));
|
||||
if (upTaskOne.IsFaulted)
|
||||
throw upTaskOne.Exception!;
|
||||
else if (upTaskOne.IsCompleted)
|
||||
if (upTaskOne.IsCompleted)
|
||||
throw new Exception("Never hit semaphore in first UP task.");
|
||||
}
|
||||
|
||||
|
@ -1306,7 +1298,7 @@ namespace Pulumi.Automation.Tests
|
|||
await Task.Delay(TimeSpan.FromSeconds(2));
|
||||
if (upTaskTwo.IsFaulted)
|
||||
throw upTaskTwo.Exception!;
|
||||
else if (upTaskTwo.IsCompleted)
|
||||
if (upTaskTwo.IsCompleted)
|
||||
throw new Exception("Never hit semaphore in second UP task.");
|
||||
}
|
||||
|
||||
|
@ -1370,7 +1362,7 @@ namespace Pulumi.Automation.Tests
|
|||
|
||||
try
|
||||
{
|
||||
Task.WaitAll(new Task[] { destroyTask, cancelTask });
|
||||
Task.WaitAll(destroyTask, cancelTask);
|
||||
}
|
||||
catch (AggregateException)
|
||||
{
|
||||
|
@ -1422,8 +1414,8 @@ namespace Pulumi.Automation.Tests
|
|||
var testMinVersion = SemVersion.Parse("2.21.1");
|
||||
if (errorExpected)
|
||||
{
|
||||
Action act = () => LocalWorkspace.ValidatePulumiVersion(testMinVersion, currentVersion, optOut);
|
||||
Assert.Throws<InvalidOperationException>(act);
|
||||
void ValidatePulumiVersion() => LocalWorkspace.ValidatePulumiVersion(testMinVersion, currentVersion, optOut);
|
||||
Assert.Throws<InvalidOperationException>(ValidatePulumiVersion);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace Pulumi.Automation.Tests.Serialization
|
|||
{
|
||||
public class DynamicObjectTests
|
||||
{
|
||||
private static LocalSerializer _serializer = new LocalSerializer();
|
||||
private static readonly LocalSerializer _serializer = new LocalSerializer();
|
||||
|
||||
[Fact]
|
||||
public void Dynamic_With_YamlDotNet()
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace Pulumi.Automation.Tests.Serialization
|
|||
{
|
||||
public class GeneralJsonConverterTests
|
||||
{
|
||||
private static LocalSerializer _serializer = new LocalSerializer();
|
||||
private static readonly LocalSerializer _serializer = new LocalSerializer();
|
||||
|
||||
[Fact]
|
||||
public void CanDeserializeConfigValue()
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Pulumi.Automation.Serialization;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Pulumi.Automation.Tests.Serialization
|
||||
{
|
||||
public class ProjectRuntimeJsonConverterTests
|
||||
{
|
||||
private static LocalSerializer _serializer = new LocalSerializer();
|
||||
private readonly ITestOutputHelper _output;
|
||||
private static readonly LocalSerializer _serializer = new LocalSerializer();
|
||||
|
||||
public ProjectRuntimeJsonConverterTests(ITestOutputHelper output)
|
||||
{
|
||||
_output = output;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(ProjectRuntimeName.NodeJS)]
|
||||
|
@ -71,7 +77,7 @@ namespace Pulumi.Automation.Tests.Serialization
|
|||
var runtime = new ProjectRuntime(ProjectRuntimeName.Dotnet);
|
||||
|
||||
var json = _serializer.SerializeJson(runtime);
|
||||
Console.WriteLine(json);
|
||||
_output.WriteLine(json);
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
Assert.NotNull(document);
|
||||
|
@ -91,7 +97,7 @@ namespace Pulumi.Automation.Tests.Serialization
|
|||
};
|
||||
|
||||
var json = _serializer.SerializeJson(runtime);
|
||||
Console.WriteLine(json);
|
||||
_output.WriteLine(json);
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
Assert.NotNull(document);
|
||||
|
|
|
@ -4,12 +4,19 @@ using System;
|
|||
using System.Text;
|
||||
using Pulumi.Automation.Serialization;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Pulumi.Automation.Tests.Serialization
|
||||
{
|
||||
public class ProjectRuntimeYamlConverterTests
|
||||
{
|
||||
private static LocalSerializer _serializer = new LocalSerializer();
|
||||
private readonly ITestOutputHelper _output;
|
||||
private static readonly LocalSerializer _serializer = new LocalSerializer();
|
||||
|
||||
public ProjectRuntimeYamlConverterTests(ITestOutputHelper output)
|
||||
{
|
||||
_output = output;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(ProjectRuntimeName.NodeJS)]
|
||||
|
@ -67,7 +74,7 @@ runtime:
|
|||
var runtime = new ProjectRuntime(ProjectRuntimeName.Dotnet);
|
||||
|
||||
var yaml = _serializer.SerializeYaml(runtime);
|
||||
Console.WriteLine(yaml);
|
||||
_output.WriteLine(yaml);
|
||||
|
||||
Assert.Equal("dotnet" + Environment.NewLine, yaml);
|
||||
}
|
||||
|
@ -84,7 +91,7 @@ runtime:
|
|||
};
|
||||
|
||||
var yaml = _serializer.SerializeYaml(runtime);
|
||||
Console.WriteLine(yaml);
|
||||
_output.WriteLine(yaml);
|
||||
|
||||
var expected = new StringBuilder();
|
||||
expected.AppendLine("name: dotnet");
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace Pulumi.Automation.Tests.Serialization
|
|||
{
|
||||
public class StackSettingsConfigValueJsonConverterTests
|
||||
{
|
||||
private static LocalSerializer _serializer = new LocalSerializer();
|
||||
private static readonly LocalSerializer _serializer = new LocalSerializer();
|
||||
|
||||
[Fact]
|
||||
public void CanDeserializePlainString()
|
||||
|
@ -23,7 +23,7 @@ namespace Pulumi.Automation.Tests.Serialization
|
|||
";
|
||||
|
||||
var settings = _serializer.DeserializeJson<StackSettings>(json);
|
||||
Assert.NotNull(settings?.Config);
|
||||
Assert.NotNull(settings.Config);
|
||||
Assert.True(settings!.Config!.ContainsKey("test"));
|
||||
|
||||
var value = settings.Config["test"];
|
||||
|
@ -46,7 +46,7 @@ namespace Pulumi.Automation.Tests.Serialization
|
|||
";
|
||||
|
||||
var settings = _serializer.DeserializeJson<StackSettings>(json);
|
||||
Assert.NotNull(settings?.Config);
|
||||
Assert.NotNull(settings.Config);
|
||||
Assert.True(settings!.Config!.ContainsKey("test"));
|
||||
|
||||
var value = settings.Config["test"];
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace Pulumi.Automation.Tests.Serialization
|
|||
{
|
||||
public class StackSettingsConfigValueYamlConverterTests
|
||||
{
|
||||
private static LocalSerializer _serializer = new LocalSerializer();
|
||||
private static readonly LocalSerializer _serializer = new LocalSerializer();
|
||||
|
||||
[Fact]
|
||||
public void CanDeserializePlainString()
|
||||
|
@ -20,7 +20,7 @@ config:
|
|||
";
|
||||
|
||||
var settings = _serializer.DeserializeYaml<StackSettings>(yaml);
|
||||
Assert.NotNull(settings?.Config);
|
||||
Assert.NotNull(settings.Config);
|
||||
Assert.True(settings!.Config!.ContainsKey("test"));
|
||||
|
||||
var value = settings.Config["test"];
|
||||
|
@ -39,7 +39,7 @@ config:
|
|||
";
|
||||
|
||||
var settings = _serializer.DeserializeYaml<StackSettings>(yaml);
|
||||
Assert.NotNull(settings?.Config);
|
||||
Assert.NotNull(settings.Config);
|
||||
Assert.True(settings!.Config!.ContainsKey("test"));
|
||||
|
||||
var value = settings.Config["test"];
|
||||
|
|
|
@ -5,18 +5,18 @@ using System.Collections.Generic;
|
|||
namespace Pulumi.Automation.Collections
|
||||
{
|
||||
/// Compares two dictionaries for equality by content, as F# maps would.
|
||||
internal sealed class DictionaryContentsComparer<K, V> : IEqualityComparer<IDictionary<K, V>> where K : notnull
|
||||
internal sealed class DictionaryContentsComparer<TKey, TValue> : IEqualityComparer<IDictionary<TKey, TValue>> where TKey : notnull
|
||||
{
|
||||
private readonly IEqualityComparer<K> _keyComparer;
|
||||
private readonly IEqualityComparer<V> _valueComparer;
|
||||
private readonly IEqualityComparer<TKey> _keyComparer;
|
||||
private readonly IEqualityComparer<TValue> _valueComparer;
|
||||
|
||||
public DictionaryContentsComparer(IEqualityComparer<K> keyComparer, IEqualityComparer<V> valueComparer)
|
||||
public DictionaryContentsComparer(IEqualityComparer<TKey> keyComparer, IEqualityComparer<TValue> valueComparer)
|
||||
{
|
||||
this._keyComparer = keyComparer;
|
||||
this._valueComparer = valueComparer;
|
||||
}
|
||||
|
||||
bool IEqualityComparer<IDictionary<K, V>>.Equals(IDictionary<K, V>? x, IDictionary<K, V>? y)
|
||||
bool IEqualityComparer<IDictionary<TKey, TValue>>.Equals(IDictionary<TKey, TValue>? x, IDictionary<TKey, TValue>? y)
|
||||
{
|
||||
if (x == null)
|
||||
{
|
||||
|
@ -24,7 +24,7 @@ namespace Pulumi.Automation.Collections
|
|||
}
|
||||
if (y == null)
|
||||
{
|
||||
return x == null;
|
||||
return false;
|
||||
}
|
||||
if (ReferenceEquals(x, y))
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ namespace Pulumi.Automation.Collections
|
|||
{
|
||||
return false;
|
||||
}
|
||||
var y2 = new Dictionary<K, V>(y, this._keyComparer);
|
||||
var y2 = new Dictionary<TKey, TValue>(y, this._keyComparer);
|
||||
foreach (var pair in x)
|
||||
{
|
||||
if (!y2.ContainsKey(pair.Key))
|
||||
|
@ -50,7 +50,7 @@ namespace Pulumi.Automation.Collections
|
|||
return true;
|
||||
}
|
||||
|
||||
int IEqualityComparer<IDictionary<K, V>>.GetHashCode(IDictionary<K, V> obj)
|
||||
int IEqualityComparer<IDictionary<TKey, TValue>>.GetHashCode(IDictionary<TKey, TValue> obj)
|
||||
{
|
||||
return 0; // inefficient but correct
|
||||
}
|
||||
|
|
|
@ -20,14 +20,14 @@ namespace Pulumi.Automation.Commands.Exceptions
|
|||
this.Name = name;
|
||||
}
|
||||
|
||||
private static readonly Regex NotFoundRegexPattern = new Regex("no stack named.*found");
|
||||
private static readonly Regex AlreadyExistsRegexPattern = new Regex("stack.*already exists");
|
||||
private static readonly string ConflictText = "[409] Conflict: Another update is currently in progress.";
|
||||
private static readonly Regex _notFoundRegexPattern = new Regex("no stack named.*found");
|
||||
private static readonly Regex _alreadyExistsRegexPattern = new Regex("stack.*already exists");
|
||||
private static readonly string _conflictText = "[409] Conflict: Another update is currently in progress.";
|
||||
|
||||
internal static CommandException CreateFromResult(CommandResult result)
|
||||
=> NotFoundRegexPattern.IsMatch(result.StandardError) ? new StackNotFoundException(result)
|
||||
: AlreadyExistsRegexPattern.IsMatch(result.StandardError) ? new StackAlreadyExistsException(result)
|
||||
: result.StandardError?.IndexOf(ConflictText) >= 0 ? new ConcurrentUpdateException(result)
|
||||
=> _notFoundRegexPattern.IsMatch(result.StandardError) ? new StackNotFoundException(result)
|
||||
: _alreadyExistsRegexPattern.IsMatch(result.StandardError) ? new StackAlreadyExistsException(result)
|
||||
: result.StandardError.IndexOf(_conflictText, StringComparison.Ordinal) >= 0 ? new ConcurrentUpdateException(result)
|
||||
: new CommandException(result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace Pulumi.Automation.Commands
|
|||
internal interface IPulumiCmd
|
||||
{
|
||||
Task<CommandResult> RunAsync(
|
||||
IEnumerable<string> args,
|
||||
IList<string> args,
|
||||
string workingDir,
|
||||
IDictionary<string, string?> additionalEnv,
|
||||
Action<string>? onStandardOutput = null,
|
||||
|
|
|
@ -9,7 +9,6 @@ using System.Text;
|
|||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using CliWrap;
|
||||
using Pulumi.Automation.Commands.Exceptions;
|
||||
using Pulumi.Automation.Events;
|
||||
|
@ -20,7 +19,7 @@ namespace Pulumi.Automation.Commands
|
|||
{
|
||||
|
||||
public async Task<CommandResult> RunAsync(
|
||||
IEnumerable<string> args,
|
||||
IList<string> args,
|
||||
string workingDir,
|
||||
IDictionary<string, string?> additionalEnv,
|
||||
Action<string>? onStandardOutput = null,
|
||||
|
@ -40,14 +39,11 @@ namespace Pulumi.Automation.Commands
|
|||
await eventLogWatcher.Stop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return await RunAsyncInner(args, workingDir, additionalEnv, onStandardOutput, onStandardError, eventLogFile: null, cancellationToken);
|
||||
}
|
||||
return await RunAsyncInner(args, workingDir, additionalEnv, onStandardOutput, onStandardError, eventLogFile: null, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<CommandResult> RunAsyncInner(
|
||||
IEnumerable<string> args,
|
||||
IList<string> args,
|
||||
string workingDir,
|
||||
IDictionary<string, string?> additionalEnv,
|
||||
Action<string>? onStandardOutput = null,
|
||||
|
@ -88,10 +84,7 @@ namespace Pulumi.Automation.Commands
|
|||
{
|
||||
throw CommandException.CreateFromResult(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static IReadOnlyDictionary<string, string?> PulumiEnvironment(IDictionary<string, string?> additionalEnv, bool debugCommands)
|
||||
|
@ -108,18 +101,18 @@ namespace Pulumi.Automation.Commands
|
|||
return env;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> PulumiArgs(IEnumerable<string> args, EventLogFile? eventLogFile)
|
||||
private static IList<string> PulumiArgs(IList<string> args, EventLogFile? eventLogFile)
|
||||
{
|
||||
// all commands should be run in non-interactive mode.
|
||||
// this causes commands to fail rather than prompting for input (and thus hanging indefinitely)
|
||||
if (!args.Contains("--non-interactive"))
|
||||
{
|
||||
args = args.Concat(new[] { "--non-interactive" });
|
||||
args = args.Concat(new[] { "--non-interactive" }).ToList();
|
||||
}
|
||||
|
||||
if (eventLogFile != null)
|
||||
{
|
||||
args = args.Concat(new[] { "--event-log", eventLogFile.FilePath });
|
||||
args = args.Concat(new[] { "--event-log", eventLogFile.FilePath }).ToList();
|
||||
}
|
||||
|
||||
return args;
|
||||
|
@ -132,15 +125,12 @@ namespace Pulumi.Automation.Commands
|
|||
{
|
||||
return "event-log";
|
||||
}
|
||||
else
|
||||
{
|
||||
return alphaNumWord.IsMatch(firstArgument) ? firstArgument : "event-log";
|
||||
}
|
||||
return alphaNumWord.IsMatch(firstArgument) ? firstArgument : "event-log";
|
||||
}
|
||||
|
||||
private class EventLogFile : IDisposable
|
||||
private sealed class EventLogFile : IDisposable
|
||||
{
|
||||
private bool _disposedValue;
|
||||
public string FilePath { get; }
|
||||
|
||||
public EventLogFile(string command)
|
||||
{
|
||||
|
@ -149,37 +139,21 @@ namespace Pulumi.Automation.Commands
|
|||
this.FilePath = Path.Combine(logDir, "eventlog.txt");
|
||||
}
|
||||
|
||||
public string FilePath { get; }
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
var dir = Path.GetDirectoryName(this.FilePath);
|
||||
try
|
||||
{
|
||||
Directory.Delete(dir, recursive: true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// allow graceful exit if for some reason
|
||||
// we're not able to delete the directory
|
||||
// will rely on OS to clean temp directory
|
||||
// in this case.
|
||||
Trace.TraceWarning("Ignoring exception during cleanup of {0} folder: {1}", dir, e);
|
||||
}
|
||||
}
|
||||
_disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
var dir = Path.GetDirectoryName(this.FilePath);
|
||||
try
|
||||
{
|
||||
Directory.Delete(dir, recursive: true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// allow graceful exit if for some reason
|
||||
// we're not able to delete the directory
|
||||
// will rely on OS to clean temp directory
|
||||
// in this case.
|
||||
Trace.TraceWarning("Ignoring exception during cleanup of {0} folder: {1}", dir, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
|
||||
namespace Pulumi.Automation
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -8,14 +8,14 @@ using Pulumi.Automation.Serialization;
|
|||
|
||||
namespace Pulumi.Automation.Events
|
||||
{
|
||||
internal class EventLogWatcher : IDisposable
|
||||
internal sealed class EventLogWatcher : IDisposable
|
||||
{
|
||||
private readonly LocalSerializer _localSerializer = new LocalSerializer();
|
||||
private readonly Action<EngineEvent> _onEvent;
|
||||
private const int _pollingIntervalMilliseconds = 100;
|
||||
|
||||
// We keep track of the last position in the file.
|
||||
private long _position = 0;
|
||||
private long _position;
|
||||
public string LogFile { get; }
|
||||
private readonly Task _pollingTask;
|
||||
private readonly CancellationTokenSource _internalCancellationTokenSource = new CancellationTokenSource();
|
||||
|
@ -82,6 +82,7 @@ namespace Pulumi.Automation.Events
|
|||
await ReadEventsOnce();
|
||||
await Task.Delay(_pollingIntervalMilliseconds, linkedSource.Token);
|
||||
}
|
||||
// ReSharper disable once FunctionNeverReturns
|
||||
}
|
||||
|
||||
private async Task ReadEventsOnce()
|
||||
|
@ -91,15 +92,11 @@ namespace Pulumi.Automation.Events
|
|||
return;
|
||||
}
|
||||
|
||||
using var fs = new FileStream(LogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
|
||||
{
|
||||
Position = this._position
|
||||
};
|
||||
await using var fs = new FileStream(LogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) { Position = this._position };
|
||||
using var reader = new StreamReader(fs);
|
||||
string? line;
|
||||
while (reader.Peek() >= 0)
|
||||
{
|
||||
line = await reader.ReadLineAsync();
|
||||
var line = await reader.ReadLineAsync();
|
||||
this._position = fs.Position;
|
||||
if (!string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using Pulumi.Automation.Events;
|
||||
|
||||
namespace Pulumi.Automation.Exceptions
|
||||
{
|
||||
public sealed class NoSummaryEventException : MissingExpectedEventException
|
||||
{
|
||||
internal NoSummaryEventException(string? message) : base(nameof(Events.SummaryEvent), message)
|
||||
internal NoSummaryEventException(string? message) : base(nameof(SummaryEvent), message)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using Semver;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Pulumi.Automation.Commands;
|
||||
using Pulumi.Automation.Exceptions;
|
||||
using Pulumi.Automation.Serialization;
|
||||
using Semver;
|
||||
|
||||
namespace Pulumi.Automation
|
||||
{
|
||||
|
@ -43,9 +43,9 @@ namespace Pulumi.Automation
|
|||
/// <inheritdoc/>
|
||||
public override string? PulumiHome { get; }
|
||||
|
||||
private SemVersion? pulumiVersion;
|
||||
private SemVersion? _pulumiVersion;
|
||||
/// <inheritdoc/>
|
||||
public override string PulumiVersion => pulumiVersion?.ToString() ?? throw new InvalidOperationException("Failed to get Pulumi version.");
|
||||
public override string PulumiVersion => _pulumiVersion?.ToString() ?? throw new InvalidOperationException("Failed to get Pulumi version.");
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string? SecretsProvider { get; }
|
||||
|
@ -358,11 +358,11 @@ namespace Pulumi.Automation
|
|||
!ProjectSettings.Comparer.Equals(projectSettings, existingSettings))
|
||||
{
|
||||
var path = this.FindSettingsFile();
|
||||
throw new Exceptions.ProjectSettingsConflictException(path);
|
||||
throw new ProjectSettingsConflictException(path);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly string[] SettingsExtensions = new string[] { ".yaml", ".yml", ".json" };
|
||||
private static readonly string[] _settingsExtensions = { ".yaml", ".yml", ".json" };
|
||||
|
||||
private async Task PopulatePulumiVersionAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
|
@ -376,8 +376,8 @@ namespace Pulumi.Automation
|
|||
var skipVersionCheckVar = "PULUMI_AUTOMATION_API_SKIP_VERSION_CHECK";
|
||||
var hasSkipEnvVar = this.EnvironmentVariables?.ContainsKey(skipVersionCheckVar) ?? false;
|
||||
var optOut = hasSkipEnvVar || Environment.GetEnvironmentVariable(skipVersionCheckVar) != null;
|
||||
LocalWorkspace.ValidatePulumiVersion(LocalWorkspace._minimumVersion, version, optOut);
|
||||
this.pulumiVersion = version;
|
||||
ValidatePulumiVersion(_minimumVersion, version, optOut);
|
||||
this._pulumiVersion = version;
|
||||
}
|
||||
|
||||
internal static void ValidatePulumiVersion(SemVersion minVersion, SemVersion currentVersion, bool optOut)
|
||||
|
@ -410,12 +410,8 @@ namespace Pulumi.Automation
|
|||
{
|
||||
return this._serializer.DeserializeJson<ProjectSettings>(content);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
var model = this._serializer.DeserializeYaml<ProjectSettingsModel>(content);
|
||||
return model.Convert();
|
||||
}
|
||||
var model = this._serializer.DeserializeYaml<ProjectSettingsModel>(content);
|
||||
return model.Convert();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
@ -429,7 +425,7 @@ namespace Pulumi.Automation
|
|||
|
||||
private string FindSettingsFile()
|
||||
{
|
||||
foreach (var ext in SettingsExtensions)
|
||||
foreach (var ext in _settingsExtensions)
|
||||
{
|
||||
var testPath = Path.Combine(this.WorkDir, $"Pulumi{ext}");
|
||||
if (File.Exists(testPath))
|
||||
|
@ -455,7 +451,7 @@ namespace Pulumi.Automation
|
|||
{
|
||||
var settingsName = GetStackSettingsName(stackName);
|
||||
|
||||
foreach (var ext in SettingsExtensions)
|
||||
foreach (var ext in _settingsExtensions)
|
||||
{
|
||||
var isJson = ext == ".json";
|
||||
var path = Path.Combine(this.WorkDir, $"Pulumi.{settingsName}{ext}");
|
||||
|
@ -475,7 +471,7 @@ namespace Pulumi.Automation
|
|||
var settingsName = GetStackSettingsName(stackName);
|
||||
|
||||
var foundExt = ".yaml";
|
||||
foreach (var ext in SettingsExtensions)
|
||||
foreach (var ext in _settingsExtensions)
|
||||
{
|
||||
var testPath = Path.Combine(this.WorkDir, $"Pulumi.{settingsName}{ext}");
|
||||
if (File.Exists(testPath))
|
||||
|
@ -567,7 +563,7 @@ namespace Pulumi.Automation
|
|||
/// <inheritdoc/>
|
||||
public override Task CreateStackAsync(string stackName, CancellationToken cancellationToken)
|
||||
{
|
||||
var args = new List<string>()
|
||||
var args = new List<string>
|
||||
{
|
||||
"stack",
|
||||
"init",
|
||||
|
@ -614,7 +610,7 @@ namespace Pulumi.Automation
|
|||
var tempFileName = Path.GetTempFileName();
|
||||
try
|
||||
{
|
||||
File.WriteAllText(tempFileName, state.Json.GetRawText());
|
||||
await File.WriteAllTextAsync(tempFileName, state.Json.GetRawText(), cancellationToken);
|
||||
await this.RunCommandAsync(new[] { "stack", "import", "--file", tempFileName, "--stack", stackName },
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
@ -631,7 +627,7 @@ namespace Pulumi.Automation
|
|||
/// <inheritdoc/>
|
||||
public override Task RemovePluginAsync(string? name = null, string? versionRange = null, PluginKind kind = PluginKind.Resource, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var args = new List<string>()
|
||||
var args = new List<string>
|
||||
{
|
||||
"plugin",
|
||||
"rm",
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Pulumi.Automation
|
|||
|
||||
if (y == null)
|
||||
{
|
||||
return x == null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ReferenceEquals(x, y))
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace Pulumi.Automation
|
|||
|
||||
if (y == null)
|
||||
{
|
||||
return x == null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ReferenceEquals(x, y))
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace Pulumi.Automation
|
|||
/// </summary>
|
||||
public enum ProjectRuntimeName
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
NodeJS,
|
||||
Go,
|
||||
Python,
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace Pulumi.Automation
|
|||
|
||||
if (y == null)
|
||||
{
|
||||
return x == null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ReferenceEquals(x, y))
|
||||
|
|
|
@ -48,17 +48,14 @@ namespace Pulumi.Automation
|
|||
{
|
||||
}
|
||||
|
||||
internal static ProjectSettings Default(string name) {
|
||||
var defaultSettings = new ProjectSettings(name, new ProjectRuntime(ProjectRuntimeName.Dotnet));
|
||||
defaultSettings.Main = Directory.GetCurrentDirectory();
|
||||
return defaultSettings;
|
||||
}
|
||||
internal static ProjectSettings Default(string name) =>
|
||||
new ProjectSettings(name, new ProjectRuntime(ProjectRuntimeName.Dotnet)) { Main = Directory.GetCurrentDirectory() };
|
||||
|
||||
internal bool IsDefault
|
||||
{
|
||||
get
|
||||
{
|
||||
return ProjectSettings.Comparer.Equals(this, ProjectSettings.Default(this.Name));
|
||||
return Comparer.Equals(this, Default(this.Name));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,7 +70,7 @@ namespace Pulumi.Automation
|
|||
|
||||
if (y == null)
|
||||
{
|
||||
return x == null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ReferenceEquals(x, y))
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace Pulumi.Automation
|
|||
private sealed class ProjectTemplateComparer : IEqualityComparer<ProjectTemplate>
|
||||
{
|
||||
|
||||
private IEqualityComparer<IDictionary<string, ProjectTemplateConfigValue>> _configComparer =
|
||||
private readonly IEqualityComparer<IDictionary<string, ProjectTemplateConfigValue>> _configComparer =
|
||||
new DictionaryContentsComparer<string, ProjectTemplateConfigValue>(
|
||||
EqualityComparer<string>.Default,
|
||||
ProjectTemplateConfigValue.Comparer);
|
||||
|
@ -38,7 +38,7 @@ namespace Pulumi.Automation
|
|||
|
||||
if (y == null)
|
||||
{
|
||||
return x == null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ReferenceEquals(x, y))
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace Pulumi.Automation
|
|||
|
||||
if (y == null)
|
||||
{
|
||||
return x == null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ReferenceEquals(x, y))
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.ExceptionServices;
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Pulumi.Automation
|
|||
if (stackType is null)
|
||||
throw new ArgumentNullException(nameof(stackType));
|
||||
|
||||
var pulumiStackType = typeof(Pulumi.Stack);
|
||||
var pulumiStackType = typeof(Stack);
|
||||
if (!pulumiStackType.IsAssignableFrom(stackType) || pulumiStackType == stackType)
|
||||
throw new ArgumentException($"Provided stack type must derive from {pulumiStackType.FullName}.", nameof(stackType));
|
||||
|
||||
|
@ -42,7 +42,7 @@ namespace Pulumi.Automation
|
|||
if (this._serviceProvider is null)
|
||||
throw new ArgumentNullException(nameof(this._serviceProvider), $"The provided service provider was null by the time this {nameof(PulumiFn)} was invoked.");
|
||||
|
||||
return this._serviceProvider.GetService(this._stackType) as Pulumi.Stack
|
||||
return this._serviceProvider.GetService(this._stackType) as Stack
|
||||
?? throw new ApplicationException(
|
||||
$"Failed to resolve instance of type {this._stackType.FullName} from service provider. Register the type with the service provider before this {nameof(PulumiFn)} is invoked.");
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Pulumi.Automation
|
||||
{
|
||||
internal class PulumiFn<TStack> : PulumiFn where TStack : Pulumi.Stack
|
||||
internal class PulumiFn<TStack> : PulumiFn where TStack : Stack
|
||||
{
|
||||
private readonly Func<TStack> _stackFactory;
|
||||
|
||||
|
|
|
@ -40,13 +40,13 @@ namespace Pulumi.Automation
|
|||
/// <param name="program">An asynchronous pulumi program that takes in a <see cref="CancellationToken"/>.</param>
|
||||
public static PulumiFn Create(Func<CancellationToken, Task> program)
|
||||
{
|
||||
Func<CancellationToken, Task<IDictionary<string, object?>>> wrapper = async cancellationToken =>
|
||||
async Task<IDictionary<string, object?>> Wrapper(CancellationToken cancellationToken)
|
||||
{
|
||||
await program(cancellationToken).ConfigureAwait(false);
|
||||
return ImmutableDictionary<string, object?>.Empty;
|
||||
};
|
||||
}
|
||||
|
||||
return new PulumiFnInline(wrapper);
|
||||
return new PulumiFnInline(Wrapper);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -55,13 +55,13 @@ namespace Pulumi.Automation
|
|||
/// <param name="program">An asynchronous pulumi program.</param>
|
||||
public static PulumiFn Create(Func<Task> program)
|
||||
{
|
||||
Func<CancellationToken, Task<IDictionary<string, object?>>> wrapper = async cancellationToken =>
|
||||
async Task<IDictionary<string, object?>> Wrapper(CancellationToken cancellationToken)
|
||||
{
|
||||
await program().ConfigureAwait(false);
|
||||
return ImmutableDictionary<string, object?>.Empty;
|
||||
};
|
||||
}
|
||||
|
||||
return new PulumiFnInline(wrapper);
|
||||
return new PulumiFnInline(Wrapper);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -70,13 +70,13 @@ namespace Pulumi.Automation
|
|||
/// <param name="program">A pulumi program that returns an output.</param>
|
||||
public static PulumiFn Create(Func<IDictionary<string, object?>> program)
|
||||
{
|
||||
Func<CancellationToken, Task<IDictionary<string, object?>>> wrapper = cancellationToken =>
|
||||
Task<IDictionary<string, object?>> Wrapper(CancellationToken cancellationToken)
|
||||
{
|
||||
var output = program();
|
||||
return Task.FromResult(output);
|
||||
};
|
||||
}
|
||||
|
||||
return new PulumiFnInline(wrapper);
|
||||
return new PulumiFnInline(Wrapper);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -91,7 +91,7 @@ namespace Pulumi.Automation
|
|||
/// </summary>
|
||||
/// <typeparam name="TStack">The <see cref="Pulumi.Stack"/> type.</typeparam>
|
||||
public static PulumiFn Create<TStack>()
|
||||
where TStack : Pulumi.Stack, new()
|
||||
where TStack : Stack, new()
|
||||
=> new PulumiFn<TStack>(() => new TStack());
|
||||
|
||||
/// <summary>
|
||||
|
@ -104,7 +104,7 @@ namespace Pulumi.Automation
|
|||
/// <typeparam name="TStack">The <see cref="Pulumi.Stack"/> type.</typeparam>
|
||||
/// <param name="serviceProvider">The service provider that will be used to resolve an instance of <typeparamref name="TStack"/>.</param>
|
||||
public static PulumiFn Create<TStack>(IServiceProvider serviceProvider)
|
||||
where TStack : Pulumi.Stack
|
||||
where TStack : Stack
|
||||
=> new PulumiFnServiceProvider(serviceProvider, typeof(TStack));
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
|
||||
namespace Pulumi.Automation
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading;
|
||||
|
@ -56,6 +54,7 @@ namespace Pulumi.Automation
|
|||
|
||||
this._callerContext.ExceptionDispatchInfo = await Deployment.RunInlineAsync(
|
||||
settings,
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
runner => this._callerContext.Program.InvokeAsync(runner, cts.Token))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
using Pulumi.Automation.Events;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
|
||||
// NOTE: The classes in this file are intended to align with the serialized
|
||||
// JSON types defined and versioned in sdk/go/common/apitype/events.go
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
using Pulumi.Automation.Events;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
|
||||
// NOTE: The classes in this file are intended to align with the serialized
|
||||
// JSON types defined and versioned in sdk/go/common/apitype/events.go
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Pulumi.Automation.Serialization.Json
|
|||
|
||||
if (reader.TokenType == JsonTokenType.Number)
|
||||
{
|
||||
if (reader.TryGetInt64(out long l))
|
||||
if (reader.TryGetInt64(out var l))
|
||||
{
|
||||
return l;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ namespace Pulumi.Automation.Serialization.Json
|
|||
|
||||
if (reader.TokenType == JsonTokenType.String)
|
||||
{
|
||||
if (reader.TryGetDateTime(out DateTime datetime))
|
||||
if (reader.TryGetDateTime(out var datetime))
|
||||
{
|
||||
return datetime;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
using Pulumi.Automation.Events;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
|
||||
// NOTE: The classes in this file are intended to align with the serialized
|
||||
// JSON types defined and versioned in sdk/go/common/apitype/events.go
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
using Pulumi.Automation.Events;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
|
||||
// NOTE: The classes in this file are intended to align with the serialized
|
||||
// JSON types defined and versioned in sdk/go/common/apitype/events.go
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
using Pulumi.Automation.Events;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
|
||||
// NOTE: The classes in this file are intended to align with the serialized
|
||||
// JSON types defined and versioned in sdk/go/common/apitype/events.go
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
using Pulumi.Automation.Events;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
|
||||
// NOTE: The classes in this file are intended to align with the serialized
|
||||
// JSON types defined and versioned in sdk/go/common/apitype/events.go
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
using Pulumi.Automation.Events;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
|
||||
// NOTE: The classes in this file are intended to align with the serialized
|
||||
// JSON types defined and versioned in sdk/go/common/apitype/events.go
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
using Pulumi.Automation.Events;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
|
||||
// NOTE: The classes in this file are intended to align with the serialized
|
||||
// JSON types defined and versioned in sdk/go/common/apitype/events.go
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
using Pulumi.Automation.Events;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
|
||||
// NOTE: The classes in this file are intended to align with the serialized
|
||||
// JSON types defined and versioned in sdk/go/common/apitype/events.go
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
using Pulumi.Automation.Events;
|
||||
using System.Linq;
|
||||
using Pulumi.Automation.Events;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
|
||||
// NOTE: The classes in this file are intended to align with the serialized
|
||||
// JSON types defined and versioned in sdk/go/common/apitype/events.go
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
using Pulumi.Automation.Events;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
|
||||
// NOTE: The classes in this file are intended to align with the serialized
|
||||
// JSON types defined and versioned in sdk/go/common/apitype/events.go
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
using Pulumi.Automation.Events;
|
||||
using Pulumi.Automation.Serialization.Json;
|
||||
|
||||
// NOTE: The classes in this file are intended to align with the serialized
|
||||
// JSON types defined and versioned in sdk/go/common/apitype/events.go
|
||||
|
@ -22,7 +22,9 @@ namespace Pulumi.Automation.Serialization
|
|||
new SummaryEvent(
|
||||
this.MaybeCorrupt,
|
||||
this.DurationSeconds,
|
||||
// ReSharper disable once ConstantNullCoalescingCondition
|
||||
this.ResourceChanges ?? new Dictionary<OperationType, int>(),
|
||||
// ReSharper disable once ConstantNullCoalescingCondition
|
||||
this.PolicyPacks ?? new Dictionary<string, string>());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@ namespace Pulumi.Automation.Serialization.Yaml
|
|||
{
|
||||
internal class ProjectRuntimeOptionsYamlConverter : IYamlTypeConverter
|
||||
{
|
||||
private static readonly Type Type = typeof(ProjectRuntimeOptions);
|
||||
private static readonly List<string> PropertyNames = typeof(ProjectRuntimeOptions).GetProperties().Select(x => x.Name).ToList();
|
||||
private static readonly Dictionary<string, Func<Scalar, string, Type, object?>> Readers =
|
||||
private static readonly Type _type = typeof(ProjectRuntimeOptions);
|
||||
private static readonly List<string> _propertyNames = typeof(ProjectRuntimeOptions).GetProperties().Select(x => x.Name).ToList();
|
||||
private static readonly Dictionary<string, Func<Scalar, string, Type, object?>> _readers =
|
||||
new Dictionary<string, Func<Scalar, string, Type, object?>>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
[nameof(ProjectRuntimeOptions.Binary)] = (x, p, t) => x.Value,
|
||||
|
@ -21,22 +21,21 @@ namespace Pulumi.Automation.Serialization.Yaml
|
|||
[nameof(ProjectRuntimeOptions.VirtualEnv)] = (x, p, t) => x.Value,
|
||||
};
|
||||
|
||||
public bool Accepts(Type type)
|
||||
=> type == Type;
|
||||
public bool Accepts(Type type) => type == _type;
|
||||
|
||||
public object? ReadYaml(IParser parser, Type type)
|
||||
public object ReadYaml(IParser parser, Type type)
|
||||
{
|
||||
if (!parser.TryConsume<MappingStart>(out _))
|
||||
throw new YamlException($"Unable to deserialize [{type.FullName}]. Expecting object.");
|
||||
|
||||
var values = PropertyNames.ToDictionary(x => x, x => (object?)null, StringComparer.OrdinalIgnoreCase);
|
||||
var values = _propertyNames.ToDictionary(x => x, x => (object?)null, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
do
|
||||
{
|
||||
if (!parser.TryConsume<Scalar>(out var propertyNameScalar))
|
||||
throw new YamlException($"Unable to deserialize [{type.FullName}]. Expecting a property name.");
|
||||
|
||||
if (!Readers.TryGetValue(propertyNameScalar.Value, out var readerFunc))
|
||||
if (!_readers.TryGetValue(propertyNameScalar.Value, out var readerFunc))
|
||||
throw new YamlException($"Unable to deserialize [{type.FullName}]. Invalid property [{propertyNameScalar.Value}].");
|
||||
|
||||
if (!parser.TryConsume<Scalar>(out var propertyValueScalar))
|
||||
|
|
|
@ -9,15 +9,14 @@ namespace Pulumi.Automation.Serialization.Yaml
|
|||
{
|
||||
internal class ProjectRuntimeYamlConverter : IYamlTypeConverter
|
||||
{
|
||||
private static readonly Type Type = typeof(ProjectRuntime);
|
||||
private static readonly Type OptionsType = typeof(ProjectRuntimeOptions);
|
||||
private static readonly Type _type = typeof(ProjectRuntime);
|
||||
private static readonly Type _optionsType = typeof(ProjectRuntimeOptions);
|
||||
|
||||
private readonly IYamlTypeConverter _optionsConverter = new ProjectRuntimeOptionsYamlConverter();
|
||||
|
||||
public bool Accepts(Type type)
|
||||
=> type == Type;
|
||||
public bool Accepts(Type type) => type == _type;
|
||||
|
||||
public object? ReadYaml(IParser parser, Type type)
|
||||
public object ReadYaml(IParser parser, Type type)
|
||||
{
|
||||
if (parser.TryConsume<Scalar>(out var nameValueScalar))
|
||||
{
|
||||
|
@ -51,7 +50,7 @@ namespace Pulumi.Automation.Serialization.Yaml
|
|||
if (!parser.Accept<MappingStart>(out _))
|
||||
throw new YamlException($"Unable to deserialize [{type.FullName}]. Runtime options property should be an object.");
|
||||
|
||||
var runtimeOptionsObj = this._optionsConverter.ReadYaml(parser, OptionsType);
|
||||
var runtimeOptionsObj = this._optionsConverter.ReadYaml(parser, _optionsType);
|
||||
if (!(runtimeOptionsObj is ProjectRuntimeOptions runtimeOptions))
|
||||
throw new YamlException("There was an issue deserializing the runtime options object.");
|
||||
|
||||
|
@ -87,7 +86,7 @@ namespace Pulumi.Automation.Serialization.Yaml
|
|||
emitter.Emit(new Scalar(runtime.Name.ToString().ToLower()));
|
||||
|
||||
emitter.Emit(new Scalar("options"));
|
||||
this._optionsConverter.WriteYaml(emitter, runtime.Options, OptionsType);
|
||||
this._optionsConverter.WriteYaml(emitter, runtime.Options, _optionsType);
|
||||
|
||||
emitter.Emit(new MappingEnd());
|
||||
}
|
||||
|
|
|
@ -9,12 +9,11 @@ namespace Pulumi.Automation.Serialization.Yaml
|
|||
{
|
||||
internal class StackSettingsConfigValueYamlConverter : IYamlTypeConverter
|
||||
{
|
||||
private static readonly Type Type = typeof(StackSettingsConfigValue);
|
||||
private static readonly Type _type = typeof(StackSettingsConfigValue);
|
||||
|
||||
public bool Accepts(Type type)
|
||||
=> type == Type;
|
||||
public bool Accepts(Type type) => type == _type;
|
||||
|
||||
public object? ReadYaml(IParser parser, Type type)
|
||||
public object ReadYaml(IParser parser, Type type)
|
||||
{
|
||||
// check if plain string
|
||||
if (parser.Accept<Scalar>(out var stringValue))
|
||||
|
@ -43,10 +42,7 @@ namespace Pulumi.Automation.Serialization.Yaml
|
|||
parser.MoveNext();
|
||||
return new StackSettingsConfigValue(securePropertyValue.Value, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotSupportedException("Automation API does not currently support deserializing complex objects from stack settings.");
|
||||
}
|
||||
throw new NotSupportedException("Automation API does not currently support deserializing complex objects from stack settings.");
|
||||
}
|
||||
|
||||
public void WriteYaml(IEmitter emitter, object? value, Type type)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace Pulumi.Automation
|
||||
{
|
||||
|
@ -9,8 +11,8 @@ namespace Pulumi.Automation
|
|||
/// <summary>
|
||||
/// This stack's secrets provider.
|
||||
/// </summary>
|
||||
[YamlDotNet.Serialization.YamlMember(Alias="secretsprovider")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("secretsprovider")]
|
||||
[YamlMember(Alias="secretsprovider")]
|
||||
[JsonPropertyName("secretsprovider")]
|
||||
|
||||
public string? SecretsProvider { get; set; }
|
||||
|
||||
|
@ -18,8 +20,8 @@ namespace Pulumi.Automation
|
|||
/// This is the KMS-encrypted ciphertext for the data key used for secrets
|
||||
/// encryption. Only used for cloud-based secrets providers.
|
||||
/// </summary>
|
||||
[YamlDotNet.Serialization.YamlMember(Alias="encryptedkey")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("encryptedkey")]
|
||||
[YamlMember(Alias="encryptedkey")]
|
||||
[JsonPropertyName("encryptedkey")]
|
||||
|
||||
public string? EncryptedKey { get; set; }
|
||||
|
||||
|
@ -27,8 +29,8 @@ namespace Pulumi.Automation
|
|||
/// This is this stack's base64 encoded encryption salt. Only used for
|
||||
/// passphrase-based secrets providers.
|
||||
/// </summary>
|
||||
[YamlDotNet.Serialization.YamlMember(Alias="encryptionsalt")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("encryptionsalt")]
|
||||
[YamlMember(Alias="encryptionsalt")]
|
||||
[JsonPropertyName("encryptionsalt")]
|
||||
|
||||
public string? EncryptionSalt { get; set; }
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ using System.Threading.Tasks;
|
|||
using Pulumi.Automation.Commands;
|
||||
using Pulumi.Automation.Commands.Exceptions;
|
||||
using Pulumi.Automation.Events;
|
||||
// ReSharper disable UnusedMemberInSuper.Global
|
||||
// ReSharper disable VirtualMemberNeverOverridden.Global
|
||||
|
||||
namespace Pulumi.Automation
|
||||
{
|
||||
|
@ -276,7 +278,7 @@ namespace Pulumi.Automation
|
|||
|
||||
internal async Task<CommandResult> RunStackCommandAsync(
|
||||
string stackName,
|
||||
IEnumerable<string> args,
|
||||
IList<string> args,
|
||||
Action<string>? onStandardOutput,
|
||||
Action<string>? onStandardError,
|
||||
Action<EngineEvent>? onEngineEvent,
|
||||
|
@ -291,12 +293,12 @@ namespace Pulumi.Automation
|
|||
}
|
||||
|
||||
internal Task<CommandResult> RunCommandAsync(
|
||||
IEnumerable<string> args,
|
||||
IList<string> args,
|
||||
CancellationToken cancellationToken)
|
||||
=> this.RunCommandAsync(args, onStandardOutput: null, onStandardError: null, onEngineEvent: null, cancellationToken);
|
||||
|
||||
internal Task<CommandResult> RunCommandAsync(
|
||||
IEnumerable<string> args,
|
||||
IList<string> args,
|
||||
Action<string>? onStandardOutput,
|
||||
Action<string>? onStandardError,
|
||||
Action<EngineEvent>? onEngineEvent,
|
||||
|
|
|
@ -5,7 +5,6 @@ using System.Collections.Generic;
|
|||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.ExceptionServices;
|
||||
|
@ -117,30 +116,23 @@ namespace Pulumi.Automation
|
|||
this.Name = name;
|
||||
this.Workspace = workspace;
|
||||
|
||||
switch (mode)
|
||||
this._readyTask = mode switch
|
||||
{
|
||||
case WorkspaceStackInitMode.Create:
|
||||
this._readyTask = workspace.CreateStackAsync(name, cancellationToken);
|
||||
break;
|
||||
case WorkspaceStackInitMode.Select:
|
||||
this._readyTask = workspace.SelectStackAsync(name, cancellationToken);
|
||||
break;
|
||||
case WorkspaceStackInitMode.CreateOrSelect:
|
||||
this._readyTask = Task.Run(async () =>
|
||||
WorkspaceStackInitMode.Create => workspace.CreateStackAsync(name, cancellationToken),
|
||||
WorkspaceStackInitMode.Select => workspace.SelectStackAsync(name, cancellationToken),
|
||||
WorkspaceStackInitMode.CreateOrSelect => Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
await workspace.CreateStackAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (StackAlreadyExistsException)
|
||||
{
|
||||
await workspace.SelectStackAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException($"Unexpected Stack creation mode: {mode}");
|
||||
}
|
||||
await workspace.CreateStackAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (StackAlreadyExistsException)
|
||||
{
|
||||
await workspace.SelectStackAsync(name, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}),
|
||||
_ => throw new InvalidOperationException($"Unexpected Stack creation mode: {mode}")
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -211,7 +203,7 @@ namespace Pulumi.Automation
|
|||
{
|
||||
var execKind = ExecKind.Local;
|
||||
var program = this.Workspace.Program;
|
||||
var args = new List<string>()
|
||||
var args = new List<string>
|
||||
{
|
||||
"up",
|
||||
"--yes",
|
||||
|
@ -313,7 +305,7 @@ namespace Pulumi.Automation
|
|||
{
|
||||
var execKind = ExecKind.Local;
|
||||
var program = this.Workspace.Program;
|
||||
var args = new List<string>() { "preview" };
|
||||
var args = new List<string> { "preview" };
|
||||
|
||||
if (options != null)
|
||||
{
|
||||
|
@ -423,7 +415,7 @@ namespace Pulumi.Automation
|
|||
RefreshOptions? options = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var args = new List<string>()
|
||||
var args = new List<string>
|
||||
{
|
||||
"refresh",
|
||||
"--yes",
|
||||
|
@ -478,7 +470,7 @@ namespace Pulumi.Automation
|
|||
DestroyOptions? options = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var args = new List<string>()
|
||||
var args = new List<string>
|
||||
{
|
||||
"destroy",
|
||||
"--yes",
|
||||
|
@ -539,7 +531,7 @@ namespace Pulumi.Automation
|
|||
HistoryOptions? options = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var args = new List<string>()
|
||||
var args = new List<string>
|
||||
{
|
||||
"stack",
|
||||
"history",
|
||||
|
@ -616,14 +608,13 @@ namespace Pulumi.Automation
|
|||
}
|
||||
|
||||
private async Task<CommandResult> RunCommandAsync(
|
||||
IEnumerable<string> args,
|
||||
IList<string> args,
|
||||
Action<string>? onStandardOutput,
|
||||
Action<string>? onStandardError,
|
||||
Action<EngineEvent>? onEngineEvent,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var argsList = args.ToList();
|
||||
argsList.AddRange(new List<string>() { "--stack", this.Name });
|
||||
args = args.Concat(new[] { "--stack", this.Name }).ToList();
|
||||
return await this.Workspace.RunStackCommandAsync(this.Name, args, onStandardOutput, onStandardError, onEngineEvent, cancellationToken);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
// Copyright 2016-2019, Pulumi Corporation
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Pulumi.Serialization;
|
||||
using Xunit;
|
||||
|
||||
namespace Pulumi.Tests.Core
|
||||
|
@ -16,14 +12,18 @@ namespace Pulumi.Tests.Core
|
|||
public Task MergeInputMaps()
|
||||
=> RunInPreview(async () =>
|
||||
{
|
||||
var map1 = new InputMap<string>();
|
||||
map1.Add("K1", "V1");
|
||||
map1.Add("K2", Output.Create("V2"));
|
||||
map1.Add("K3", Output.Create("V3_wrong"));
|
||||
var map1 = new InputMap<string>
|
||||
{
|
||||
{ "K1", "V1" },
|
||||
{ "K2", Output.Create("V2") },
|
||||
{ "K3", Output.Create("V3_wrong") }
|
||||
};
|
||||
|
||||
var map2 = new InputMap<string>();
|
||||
map2.Add("K3", Output.Create("V3"));
|
||||
map2.Add("K4", "V4");
|
||||
var map2 = new InputMap<string>
|
||||
{
|
||||
{ "K3", Output.Create("V3") },
|
||||
{ "K4", "V4" }
|
||||
};
|
||||
|
||||
var result = InputMap<string>.Merge(map1, map2);
|
||||
|
||||
|
@ -31,7 +31,7 @@ namespace Pulumi.Tests.Core
|
|||
var data = await result.ToOutput().DataTask.ConfigureAwait(false);
|
||||
Assert.True(data.IsKnown);
|
||||
Assert.Equal(4, data.Value.Count);
|
||||
for (int i = 1; i <=4; i++)
|
||||
for (var i = 1; i <=4; i++)
|
||||
Assert.True(data.Value.Contains($"K{i}", $"V{i}"));
|
||||
|
||||
// Check that the input maps haven't changed
|
||||
|
|
|
@ -8,7 +8,7 @@ using Xunit;
|
|||
|
||||
namespace Pulumi.Tests.Core
|
||||
{
|
||||
public partial class OutputTests : PulumiTest
|
||||
public class OutputTests : PulumiTest
|
||||
{
|
||||
private static Output<T> CreateOutput<T>(T value, bool isKnown, bool isSecret = false)
|
||||
=> new Output<T>(Task.FromResult(OutputData.Create(
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
using System.Collections.Immutable;
|
||||
using System.Threading.Tasks;
|
||||
using Pulumi.Serialization;
|
||||
using Xunit;
|
||||
|
||||
namespace Pulumi.Tests.Core
|
||||
|
@ -17,7 +16,8 @@ namespace Pulumi.Tests.Core
|
|||
[Input("array")] private InputList<bool> _array = null!;
|
||||
public InputList<bool> Array
|
||||
{
|
||||
get => _array ?? (_array = new InputList<bool>());
|
||||
// ReSharper disable once ConstantNullCoalescingCondition
|
||||
get => _array ??= new InputList<bool>();
|
||||
set => _array = value;
|
||||
}
|
||||
}
|
||||
|
@ -90,14 +90,16 @@ namespace Pulumi.Tests.Core
|
|||
[Input("array", json: true)] private InputList<bool> _array = null!;
|
||||
public InputList<bool> Array
|
||||
{
|
||||
get => _array ?? (_array = new InputList<bool>());
|
||||
// ReSharper disable once ConstantNullCoalescingCondition
|
||||
get => _array ??= new InputList<bool>();
|
||||
set => _array = value;
|
||||
}
|
||||
|
||||
[Input("map", json: true)] private InputMap<int> _map = null!;
|
||||
public InputMap<int> Map
|
||||
{
|
||||
get => _map ?? (_map = new InputMap<int>());
|
||||
// ReSharper disable once ConstantNullCoalescingCondition
|
||||
get => _map ??= new InputMap<int>();
|
||||
set => _map = value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,23 +17,16 @@ namespace Pulumi.Tests.Mocks
|
|||
return Task.FromResult<object>(args);
|
||||
}
|
||||
|
||||
public Task<(string? id, object state)> NewResourceAsync(MockResourceArgs args)
|
||||
{
|
||||
switch (args.Type)
|
||||
public Task<(string? id, object state)> NewResourceAsync(MockResourceArgs args) =>
|
||||
args.Type switch
|
||||
{
|
||||
case "aws:ec2/instance:Instance":
|
||||
return Task.FromResult<(string?, object)>(("i-1234567890abcdef0", new Dictionary<string, object> {
|
||||
{ "publicIp", "203.0.113.12" },
|
||||
}));
|
||||
case "pkg:index:MyCustom":
|
||||
return Task.FromResult<(string?, object)>((args.Name + "_id", args.Inputs));
|
||||
default:
|
||||
throw new Exception($"Unknown resource {args.Type}");
|
||||
}
|
||||
}
|
||||
"aws:ec2/instance:Instance" => Task.FromResult<(string?, object)>(("i-1234567890abcdef0", new Dictionary<string, object> { { "publicIp", "203.0.113.12" }, })),
|
||||
"pkg:index:MyCustom" => Task.FromResult<(string?, object)>((args.Name + "_id", args.Inputs)),
|
||||
_ => throw new Exception($"Unknown resource {args.Type}")
|
||||
};
|
||||
}
|
||||
|
||||
public partial class MocksTests
|
||||
public class MocksTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task TestCustom()
|
||||
|
@ -43,7 +36,7 @@ namespace Pulumi.Tests.Mocks
|
|||
var instance = resources.OfType<Instance>().FirstOrDefault();
|
||||
Assert.NotNull(instance);
|
||||
|
||||
var ip = await instance.PublicIp.GetValueAsync();
|
||||
var ip = await instance!.PublicIp.GetValueAsync();
|
||||
Assert.Equal("203.0.113.12", ip);
|
||||
}
|
||||
|
||||
|
@ -52,10 +45,10 @@ namespace Pulumi.Tests.Mocks
|
|||
{
|
||||
var resources = await Testing.RunAsync<MyStack>();
|
||||
|
||||
var mycustom = resources.OfType<MyCustom>().FirstOrDefault();
|
||||
Assert.NotNull(mycustom);
|
||||
var myCustom = resources.OfType<MyCustom>().FirstOrDefault();
|
||||
Assert.NotNull(myCustom);
|
||||
|
||||
var instance = await mycustom.Instance.GetValueAsync();
|
||||
var instance = await myCustom!.Instance.GetValueAsync();
|
||||
Assert.IsType<Instance>(instance);
|
||||
|
||||
var ip = await instance.PublicIp.GetValueAsync();
|
||||
|
@ -70,7 +63,7 @@ namespace Pulumi.Tests.Mocks
|
|||
var stack = resources.OfType<MyStack>().FirstOrDefault();
|
||||
Assert.NotNull(stack);
|
||||
|
||||
var ip = await stack.PublicIp.GetValueAsync();
|
||||
var ip = await stack!.PublicIp.GetValueAsync();
|
||||
Assert.Equal("203.0.113.12", ip);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,33 +3,33 @@
|
|||
namespace Pulumi.Tests.Mocks
|
||||
{
|
||||
[ResourceType("aws:ec2/instance:Instance", null)]
|
||||
public partial class Instance : Pulumi.CustomResource
|
||||
public class Instance : CustomResource
|
||||
{
|
||||
[Output("publicIp")]
|
||||
public Output<string> PublicIp { get; private set; } = null!;
|
||||
|
||||
public Instance(string name, InstanceArgs args, CustomResourceOptions? options = null)
|
||||
: base("aws:ec2/instance:Instance", name, args ?? new InstanceArgs(), options)
|
||||
: base("aws:ec2/instance:Instance", name, args, options)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class InstanceArgs : Pulumi.ResourceArgs
|
||||
public sealed class InstanceArgs : ResourceArgs
|
||||
{
|
||||
}
|
||||
|
||||
public partial class MyCustom : Pulumi.CustomResource
|
||||
public class MyCustom : CustomResource
|
||||
{
|
||||
[Output("instance")]
|
||||
public Output<Instance> Instance { get; private set; } = null!;
|
||||
|
||||
public MyCustom(string name, MyCustomArgs args, CustomResourceOptions? options = null)
|
||||
: base("pkg:index:MyCustom", name, args ?? new MyCustomArgs(), options)
|
||||
: base("pkg:index:MyCustom", name, args, options)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MyCustomArgs : Pulumi.ResourceArgs
|
||||
public sealed class MyCustomArgs : ResourceArgs
|
||||
{
|
||||
[Input("instance")]
|
||||
public Input<Instance>? Instance { get; set; }
|
||||
|
@ -38,15 +38,12 @@ namespace Pulumi.Tests.Mocks
|
|||
public class MyStack : Stack
|
||||
{
|
||||
[Output("publicIp")]
|
||||
public Output<string> PublicIp { get; private set; } = null!;
|
||||
public Output<string> PublicIp { get; private set; }
|
||||
|
||||
public MyStack()
|
||||
{
|
||||
var myInstance = new Instance("instance", new InstanceArgs());
|
||||
var myCustom = new MyCustom("mycustom", new MyCustomArgs
|
||||
{
|
||||
Instance = myInstance,
|
||||
});
|
||||
new MyCustom("mycustom", new MyCustomArgs { Instance = myInstance });
|
||||
this.PublicIp = myInstance.PublicIp;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace Pulumi.Tests.Serialization
|
|||
{
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
var data = Converter.ConvertValue<bool>("", new Value { StringValue = "" });
|
||||
Converter.ConvertValue<bool>("", new Value { StringValue = "" });
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ namespace Pulumi.Tests.Serialization
|
|||
{
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
var data = Converter.ConvertValue<bool>("", new Value { StringValue = "" });
|
||||
Converter.ConvertValue<bool>("", new Value { StringValue = "" });
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace Pulumi.Tests.Serialization
|
|||
public override bool Equals(object? obj) => obj is ContainerColor other && Equals(other);
|
||||
public bool Equals(ContainerColor other) => string.Equals(_value, other._value, StringComparison.Ordinal);
|
||||
|
||||
public override int GetHashCode() => _value?.GetHashCode() ?? 0;
|
||||
public override int GetHashCode() => _value.GetHashCode();
|
||||
|
||||
public override string ToString() => _value;
|
||||
}
|
||||
|
|
|
@ -3,9 +3,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Pulumi.Serialization;
|
||||
using Xunit;
|
||||
using Type = System.Type;
|
||||
|
||||
namespace Pulumi.Tests.Serialization
|
||||
{
|
||||
|
@ -35,7 +38,7 @@ namespace Pulumi.Tests.Serialization
|
|||
public bool Equals(ContainerColor other) => string.Equals(_value, other._value, StringComparison.Ordinal);
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public override int GetHashCode() => _value?.GetHashCode() ?? 0;
|
||||
public override int GetHashCode() => _value.GetHashCode();
|
||||
|
||||
public override string ToString() => _value;
|
||||
}
|
||||
|
@ -60,12 +63,13 @@ namespace Pulumi.Tests.Serialization
|
|||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public override bool Equals(object? obj) => obj is ContainerBrightness other && Equals(other);
|
||||
// ReSharper disable once CompareOfFloatsByEqualityOperator
|
||||
public bool Equals(ContainerBrightness other) => _value == other._value;
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public override int GetHashCode() => _value.GetHashCode();
|
||||
|
||||
public override string ToString() => _value.ToString();
|
||||
public override string ToString() => _value.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public enum ContainerSize
|
||||
|
@ -196,14 +200,14 @@ namespace Pulumi.Tests.Serialization
|
|||
public static IEnumerable<object[]> EnumsWithUnconvertibleValues()
|
||||
=> new[]
|
||||
{
|
||||
new object[] { typeof(ContainerColor), new Google.Protobuf.WellKnownTypes.Value { NumberValue = 1.0 } },
|
||||
new object[] { typeof(ContainerBrightness), new Google.Protobuf.WellKnownTypes.Value { StringValue = "hello" } },
|
||||
new object[] { typeof(ContainerSize), new Google.Protobuf.WellKnownTypes.Value { StringValue = "hello" } },
|
||||
new object[] { typeof(ContainerColor), new Value { NumberValue = 1.0 } },
|
||||
new object[] { typeof(ContainerBrightness), new Value { StringValue = "hello" } },
|
||||
new object[] { typeof(ContainerSize), new Value { StringValue = "hello" } },
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(EnumsWithUnconvertibleValues))]
|
||||
public void ConvertingUnconvertibleValuesThrows(Type targetType, Google.Protobuf.WellKnownTypes.Value value)
|
||||
public void ConvertingUnconvertibleValuesThrows(Type targetType, Value value)
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
// Copyright 2016-2019, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Threading.Tasks;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Pulumi.Serialization;
|
||||
using Xunit;
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Pulumi.Tests.Serialization
|
|||
{
|
||||
public class ResourceRefPropertyTests : ConverterTests
|
||||
{
|
||||
public sealed class MyArgs : Pulumi.ResourceArgs
|
||||
public sealed class MyArgs : ResourceArgs
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -52,18 +52,18 @@ namespace Pulumi.Tests.Serialization
|
|||
{
|
||||
public MyStack()
|
||||
{
|
||||
var customResource = new MyCustomResource("test", null, null);
|
||||
var componentResource = new MyComponentResource("test", null, null);
|
||||
new MyCustomResource("test", null);
|
||||
new MyComponentResource("test", null);
|
||||
}
|
||||
}
|
||||
|
||||
class MyMocks : IMocks
|
||||
{
|
||||
bool isPreview;
|
||||
private readonly bool _isPreview;
|
||||
|
||||
public MyMocks(bool isPreview)
|
||||
{
|
||||
this.isPreview = isPreview;
|
||||
this._isPreview = isPreview;
|
||||
}
|
||||
|
||||
public Task<object> CallAsync(MockCallArgs args)
|
||||
|
@ -77,10 +77,10 @@ namespace Pulumi.Tests.Serialization
|
|||
{
|
||||
case "test:index:resource":
|
||||
case "test:missing:resource":
|
||||
return Task.FromResult<(string?, object)>((this.isPreview ? null : "id", new Dictionary<string, object> {}));
|
||||
return Task.FromResult<(string?, object)>((this._isPreview ? null : "id", new Dictionary<string, object>()));
|
||||
case "test:index:component":
|
||||
case "test:missing:component":
|
||||
return Task.FromResult<(string?, object)>((null, new Dictionary<string, object> {}));
|
||||
return Task.FromResult<(string?, object)>((null, new Dictionary<string, object>()));
|
||||
default:
|
||||
throw new Exception($"Unknown resource {args.Type}");
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ namespace Pulumi.Tests.Serialization
|
|||
var res = resources.OfType<MyCustomResource>().FirstOrDefault();
|
||||
Assert.NotNull(res);
|
||||
|
||||
var urn = (await res.Urn.DataTask).Value;
|
||||
var urn = (await res!.Urn.DataTask).Value;
|
||||
var id = (await res.Id.DataTask).Value;
|
||||
|
||||
var v = await SerializeToValueAsync(res);
|
||||
|
@ -145,7 +145,7 @@ namespace Pulumi.Tests.Serialization
|
|||
var res = resources.OfType<MyCustomResource>().FirstOrDefault();
|
||||
Assert.NotNull(res);
|
||||
|
||||
var id = await SerializeToValueAsync(res.Id);
|
||||
var id = await SerializeToValueAsync(res!.Id);
|
||||
|
||||
var v = await SerializeToValueAsync(res, false);
|
||||
Assert.Equal(id, v);
|
||||
|
@ -154,11 +154,11 @@ namespace Pulumi.Tests.Serialization
|
|||
public class DeserializeCustomResourceStack : Stack
|
||||
{
|
||||
[Output("values")]
|
||||
public Output<ImmutableDictionary<string, string>> Values { get; private set; } = null!;
|
||||
public Output<ImmutableDictionary<string, string>> Values { get; private set; }
|
||||
|
||||
public DeserializeCustomResourceStack()
|
||||
{
|
||||
var res = new MyCustomResource("test", null, null);
|
||||
var res = new MyCustomResource("test", null);
|
||||
|
||||
var urn = res.Urn.DataTask.Result.Value;
|
||||
var id = res.Id.DataTask.Result.Value;
|
||||
|
@ -184,7 +184,7 @@ namespace Pulumi.Tests.Serialization
|
|||
var stack = resources.OfType<DeserializeCustomResourceStack>().FirstOrDefault();
|
||||
Assert.NotNull(stack);
|
||||
|
||||
var values = (await stack.Values.DataTask).Value;
|
||||
var values = (await stack!.Values.DataTask).Value;
|
||||
Assert.Equal(values["expectedUrn"], values["actualUrn"]);
|
||||
Assert.Equal(values["expectedId"], values["actualId"]);
|
||||
}
|
||||
|
@ -192,11 +192,11 @@ namespace Pulumi.Tests.Serialization
|
|||
public class DeserializeMissingCustomResourceStack : Stack
|
||||
{
|
||||
[Output("values")]
|
||||
public Output<ImmutableDictionary<string, string>> Values { get; private set; } = null!;
|
||||
public Output<ImmutableDictionary<string, string>> Values { get; private set; }
|
||||
|
||||
public DeserializeMissingCustomResourceStack()
|
||||
{
|
||||
var res = new MissingCustomResource("test", null, null);
|
||||
var res = new MissingCustomResource("test", null);
|
||||
|
||||
var urn = res.Urn.DataTask.Result.Value;
|
||||
|
||||
|
@ -219,7 +219,7 @@ namespace Pulumi.Tests.Serialization
|
|||
var stack = resources.OfType<DeserializeMissingCustomResourceStack>().FirstOrDefault();
|
||||
Assert.NotNull(stack);
|
||||
|
||||
var values = (await stack.Values.DataTask).Value;
|
||||
var values = (await stack!.Values.DataTask).Value;
|
||||
Assert.Equal(values["expectedUrn"], values["actualUrn"]);
|
||||
}
|
||||
|
||||
|
@ -232,7 +232,7 @@ namespace Pulumi.Tests.Serialization
|
|||
var res = resources.OfType<MyComponentResource>().FirstOrDefault();
|
||||
Assert.NotNull(res);
|
||||
|
||||
var urn = (await res.Urn.DataTask).Value;
|
||||
var urn = (await res!.Urn.DataTask).Value;
|
||||
|
||||
var v = await SerializeToValueAsync(res);
|
||||
Assert.Equal(CreateComponentResourceReference(urn), v);
|
||||
|
@ -247,7 +247,7 @@ namespace Pulumi.Tests.Serialization
|
|||
var res = resources.OfType<MyComponentResource>().FirstOrDefault();
|
||||
Assert.NotNull(res);
|
||||
|
||||
var urn = await SerializeToValueAsync(res.Urn);
|
||||
var urn = await SerializeToValueAsync(res!.Urn);
|
||||
|
||||
var v = await SerializeToValueAsync(res, false);
|
||||
Assert.Equal(urn, v);
|
||||
|
@ -256,11 +256,11 @@ namespace Pulumi.Tests.Serialization
|
|||
public class DeserializeComponentResourceStack : Stack
|
||||
{
|
||||
[Output("values")]
|
||||
public Output<ImmutableDictionary<string, string>> Values { get; private set; } = null!;
|
||||
public Output<ImmutableDictionary<string, string>> Values { get; private set; }
|
||||
|
||||
public DeserializeComponentResourceStack()
|
||||
{
|
||||
var res = new MyComponentResource("test", null, null);
|
||||
var res = new MyComponentResource("test", null);
|
||||
|
||||
var urn = res.Urn.DataTask.Result.Value;
|
||||
|
||||
|
@ -283,18 +283,18 @@ namespace Pulumi.Tests.Serialization
|
|||
var stack = resources.OfType<DeserializeComponentResourceStack>().FirstOrDefault();
|
||||
Assert.NotNull(stack);
|
||||
|
||||
var values = (await stack.Values.DataTask).Value;
|
||||
var values = (await stack!.Values.DataTask).Value;
|
||||
Assert.Equal(values["expectedUrn"], values["actualUrn"]);
|
||||
}
|
||||
|
||||
public class DeserializeMissingComponentResourceStack : Stack
|
||||
{
|
||||
[Output("values")]
|
||||
public Output<ImmutableDictionary<string, string>> Values { get; private set; } = null!;
|
||||
public Output<ImmutableDictionary<string, string>> Values { get; private set; }
|
||||
|
||||
public DeserializeMissingComponentResourceStack()
|
||||
{
|
||||
var res = new MissingComponentResource("test", null, null);
|
||||
var res = new MissingComponentResource("test", null);
|
||||
|
||||
var urn = res.Urn.DataTask.Result.Value;
|
||||
|
||||
|
@ -317,7 +317,7 @@ namespace Pulumi.Tests.Serialization
|
|||
var stack = resources.OfType<DeserializeMissingComponentResourceStack>().FirstOrDefault();
|
||||
Assert.NotNull(stack);
|
||||
|
||||
var values = (await stack.Values.DataTask).Value;
|
||||
var values = (await stack!.Values.DataTask).Value;
|
||||
Assert.Equal(values["expectedUrn"], values["actualUrn"]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace Pulumi.Tests.Serialization
|
|||
{
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
var data = Converter.ConvertValue<Union<int, string>>("", new Value { BoolValue = true });
|
||||
Converter.ConvertValue<Union<int, string>>("", new Value { BoolValue = true });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace Pulumi.Tests
|
|||
private class NullOutputStack : Stack
|
||||
{
|
||||
[Output("foo")]
|
||||
public Output<string>? Foo { get; }
|
||||
public Output<string>? Foo { get; } = null;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -46,7 +46,7 @@ namespace Pulumi.Tests
|
|||
{
|
||||
try
|
||||
{
|
||||
var (stack, outputs) = await Run<NullOutputStack>();
|
||||
await Run<NullOutputStack>();
|
||||
}
|
||||
catch (RunException ex)
|
||||
{
|
||||
|
@ -73,7 +73,7 @@ namespace Pulumi.Tests
|
|||
{
|
||||
try
|
||||
{
|
||||
var (stack, outputs) = await Run<InvalidOutputTypeStack>();
|
||||
await Run<InvalidOutputTypeStack>();
|
||||
}
|
||||
catch (RunException ex)
|
||||
{
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright 2016-2019, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.Json;
|
||||
|
@ -32,14 +31,10 @@ namespace Pulumi
|
|||
/// </summary>
|
||||
public Config(string? name = null)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
name = Deployment.Instance.ProjectName;
|
||||
}
|
||||
|
||||
name ??= Deployment.Instance.ProjectName;
|
||||
if (name.EndsWith(":config", StringComparison.Ordinal))
|
||||
{
|
||||
name = name[0..^":config".Length];
|
||||
name = name[..^":config".Length];
|
||||
}
|
||||
|
||||
_name = name;
|
||||
|
@ -84,9 +79,13 @@ namespace Pulumi
|
|||
private bool? GetBooleanImpl(string key, string? use = null, [CallerMemberName] string? insteadOf = null)
|
||||
{
|
||||
var v = GetImpl(key, use, insteadOf);
|
||||
return v == null ? default(bool?) :
|
||||
v == "true" ? true :
|
||||
v == "false" ? false : throw new ConfigTypeException(FullKey(key), v, nameof(Boolean));
|
||||
return v switch
|
||||
{
|
||||
null => default(bool?),
|
||||
"true" => true,
|
||||
"false" => false,
|
||||
_ => throw new ConfigTypeException(FullKey(key), v, nameof(Boolean))
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -155,8 +154,7 @@ namespace Pulumi
|
|||
/// <summary>
|
||||
/// Loads an optional configuration value, as an object, by its key, marking it as a secret
|
||||
/// or null if it doesn't exist. This works by taking the value associated with <paramref
|
||||
/// name="key"/> and passing it to <see cref="JsonSerializer.Deserialize{TValue}(string,
|
||||
/// JsonSerializerOptions)"/>.
|
||||
/// name="key"/> and passing it to <see cref="JsonSerializer.Deserialize{TValue}(string, JsonSerializerOptions)"/>.
|
||||
/// </summary>
|
||||
public Output<T>? GetSecretObject<T>(string key)
|
||||
{
|
||||
|
@ -238,8 +236,8 @@ namespace Pulumi
|
|||
/// <summary>
|
||||
/// Loads a configuration value as a JSON string and deserializes the JSON into a JavaScript
|
||||
/// object, marking it as a secret. If it doesn't exist, or the configuration value cannot
|
||||
/// be converted using <see cref="JsonSerializer.Deserialize{TValue}(string,
|
||||
/// JsonSerializerOptions)"/>. an error is thrown.
|
||||
/// be converted using <see cref="JsonSerializer.Deserialize{TValue}(string, JsonSerializerOptions)"/>,
|
||||
/// an error is thrown.
|
||||
/// </summary>
|
||||
public Output<T> RequireSecretObject<T>(string key)
|
||||
=> Output.CreateSecret(RequireObjectImpl<T>(key));
|
||||
|
|
|
@ -11,12 +11,7 @@ namespace Pulumi
|
|||
/// </summary>
|
||||
private class ConfigTypeException : RunException
|
||||
{
|
||||
public ConfigTypeException(string key, object? v, string expectedType)
|
||||
: this(key, v, expectedType, innerException: null)
|
||||
{
|
||||
}
|
||||
|
||||
public ConfigTypeException(string key, object? v, string expectedType, Exception? innerException)
|
||||
public ConfigTypeException(string key, object? v, string expectedType, Exception? innerException = null)
|
||||
: base($"Configuration '{key}' value '{v}' is not a valid {expectedType}", innerException)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// Copyright 2016-2019, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
|
||||
namespace Pulumi
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -13,9 +15,9 @@ namespace Pulumi
|
|||
|
||||
private protected AssetOrArchive(string sigKey, string propName, object value)
|
||||
{
|
||||
SigKey = sigKey ?? throw new System.ArgumentNullException(nameof(sigKey));
|
||||
PropName = propName ?? throw new System.ArgumentNullException(nameof(propName));
|
||||
Value = value ?? throw new System.ArgumentNullException(nameof(value));
|
||||
SigKey = sigKey ?? throw new ArgumentNullException(nameof(sigKey));
|
||||
PropName = propName ?? throw new ArgumentNullException(nameof(propName));
|
||||
Value = value ?? throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,13 +127,13 @@ namespace Pulumi
|
|||
#region construct from Output of some list type.
|
||||
|
||||
public static implicit operator InputList<T>(Output<T[]> values)
|
||||
=> values.Apply(a => ImmutableArray.CreateRange(a));
|
||||
=> values.Apply(ImmutableArray.CreateRange);
|
||||
|
||||
public static implicit operator InputList<T>(Output<List<T>> values)
|
||||
=> values.Apply(a => ImmutableArray.CreateRange(a));
|
||||
=> values.Apply(ImmutableArray.CreateRange);
|
||||
|
||||
public static implicit operator InputList<T>(Output<IEnumerable<T>> values)
|
||||
=> values.Apply(a => ImmutableArray.CreateRange(a));
|
||||
=> values.Apply(ImmutableArray.CreateRange);
|
||||
|
||||
public static implicit operator InputList<T>(Output<ImmutableArray<T>> values)
|
||||
=> new InputList<T>(values);
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Pulumi
|
|||
/// <see cref="Resource"/>. The individual values are themselves <see cref="Input{T}"/>s. i.e.
|
||||
/// the individual values can be concrete values or <see cref="Output{T}"/>s.
|
||||
/// <para/>
|
||||
/// <see cref="InputMap{V}"/> differs from a normal <see cref="IDictionary{K,V}"/> in that it is
|
||||
/// <see cref="InputMap{V}"/> differs from a normal <see cref="IDictionary{TKey,TValue}"/> in that it is
|
||||
/// itself an <see cref="Input{T}"/>. For example, a <see cref="Resource"/> that accepts an
|
||||
/// <see cref="InputMap{V}"/> will accept not just a dictionary but an <see cref="Output{T}"/>
|
||||
/// of a dictionary as well. This is important for cases where the <see cref="Output{T}"/>
|
||||
|
@ -96,10 +96,10 @@ namespace Pulumi
|
|||
=> Output.Create(values);
|
||||
|
||||
public static implicit operator InputMap<V>(Output<Dictionary<string, V>> values)
|
||||
=> values.Apply(d => ImmutableDictionary.CreateRange(d));
|
||||
=> values.Apply(ImmutableDictionary.CreateRange);
|
||||
|
||||
public static implicit operator InputMap<V>(Output<IDictionary<string, V>> values)
|
||||
=> values.Apply(d => ImmutableDictionary.CreateRange(d));
|
||||
=> values.Apply(ImmutableDictionary.CreateRange);
|
||||
|
||||
public static implicit operator InputMap<V>(Output<ImmutableDictionary<string, V>> values)
|
||||
=> new InputMap<V>(values);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// Copyright 2016-2019, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
|
||||
namespace Pulumi
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -29,10 +27,10 @@ namespace Pulumi
|
|||
=> Output.Create(value);
|
||||
|
||||
public static implicit operator InputUnion<T0, T1>(Output<T0> value)
|
||||
=> new InputUnion<T0, T1>(value.Apply(v => Union<T0, T1>.FromT0(v)));
|
||||
=> new InputUnion<T0, T1>(value.Apply(Union<T0, T1>.FromT0));
|
||||
|
||||
public static implicit operator InputUnion<T0, T1>(Output<T1> value)
|
||||
=> new InputUnion<T0, T1>(value.Apply(v => Union<T0, T1>.FromT1(v)));
|
||||
=> new InputUnion<T0, T1>(value.Apply(Union<T0, T1>.FromT1));
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright 2016-2019, Pulumi Corporation
|
||||
|
||||
// ReSharper disable NotAccessedField.Global
|
||||
namespace Pulumi
|
||||
{
|
||||
internal class Options
|
||||
|
|
|
@ -192,19 +192,19 @@ namespace Pulumi
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Apply{U}(Func{T, Output{U}})"/> for more details.
|
||||
/// <see cref="Output{T}.Apply{U}(Func{T, Output{U}})"/> for more details.
|
||||
/// </summary>
|
||||
public Output<U> Apply<U>(Func<T, U> func)
|
||||
=> Apply(t => Output.Create(func(t)));
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Apply{U}(Func{T, Output{U}})"/> for more details.
|
||||
/// <see cref="Output{T}.Apply{U}(Func{T, Output{U}})"/> for more details.
|
||||
/// </summary>
|
||||
public Output<U> Apply<U>(Func<T, Task<U>> func)
|
||||
=> Apply(t => Output.Create(func(t)));
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="Apply{U}(Func{T, Output{U}})"/> for more details.
|
||||
/// <see cref="Output{T}.Apply{U}(Func{T, Output{U}})"/> for more details.
|
||||
/// </summary>
|
||||
public Output<U> Apply<U>(Func<T, Input<U>?> func)
|
||||
=> Apply(t => func(t).ToOutput());
|
||||
|
@ -303,6 +303,7 @@ namespace Pulumi
|
|||
var isKnown = true;
|
||||
var isSecret = false;
|
||||
|
||||
#pragma warning disable 8601
|
||||
Update(await GetData(item1).ConfigureAwait(false), ref tuple.Item1);
|
||||
Update(await GetData(item2).ConfigureAwait(false), ref tuple.Item2);
|
||||
Update(await GetData(item3).ConfigureAwait(false), ref tuple.Item3);
|
||||
|
@ -311,6 +312,7 @@ namespace Pulumi
|
|||
Update(await GetData(item6).ConfigureAwait(false), ref tuple.Item6);
|
||||
Update(await GetData(item7).ConfigureAwait(false), ref tuple.Item7);
|
||||
Update(await GetData(item8).ConfigureAwait(false), ref tuple.Item8);
|
||||
#pragma warning restore 8601
|
||||
|
||||
return OutputData.Create(resources.ToImmutable(), tuple, isKnown, isSecret);
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
using System;
|
||||
using OneOf;
|
||||
|
||||
// ReSharper disable PossiblyImpureMethodCallOnReadonlyVariable
|
||||
|
||||
namespace Pulumi
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -26,7 +28,7 @@ namespace Pulumi
|
|||
/// or a <see cref="string"/> can be represented as <c>Output<int, string></c>. The <see
|
||||
/// cref="Input{T}"/> version of this is <see cref="InputUnion{T0, T1}"/>.
|
||||
/// </summary>
|
||||
public struct Union<T0, T1> : IEquatable<Union<T0, T1>>, IUnion
|
||||
public readonly struct Union<T0, T1> : IEquatable<Union<T0, T1>>, IUnion
|
||||
{
|
||||
private readonly OneOf<T0, T1> _data;
|
||||
|
||||
|
|
|
@ -66,10 +66,7 @@ namespace Pulumi
|
|||
if (childName!.StartsWith(parentName, StringComparison.Ordinal))
|
||||
{
|
||||
aliasName = parentAlias.ToOutput().Apply<string>(parentAliasUrn =>
|
||||
{
|
||||
return parentAliasUrn.Substring(parentAliasUrn.LastIndexOf("::", StringComparison.Ordinal) + 2)
|
||||
+ childName.Substring(parentName.Length);
|
||||
});
|
||||
parentAliasUrn.Substring(parentAliasUrn.LastIndexOf("::", StringComparison.Ordinal) + 2) + childName.Substring(parentName.Length));
|
||||
}
|
||||
|
||||
var urn = Create(
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -29,7 +30,7 @@ namespace Pulumi
|
|||
public Runner(IDeploymentInternal deployment)
|
||||
=> _deployment = deployment;
|
||||
|
||||
public Task<int> RunAsync<TStack>(IServiceProvider serviceProvider) where TStack : Stack
|
||||
Task<int> IRunner.RunAsync<TStack>(IServiceProvider serviceProvider)
|
||||
{
|
||||
if (serviceProvider == null)
|
||||
{
|
||||
|
@ -40,8 +41,7 @@ namespace Pulumi
|
|||
?? throw new ApplicationException($"Failed to resolve instance of type {typeof(TStack)} from service provider. Register the type with the service provider before calling {nameof(RunAsync)}."));
|
||||
}
|
||||
|
||||
public Task<int> RunAsync<TStack>() where TStack : Stack, new()
|
||||
=> RunAsync(() => new TStack());
|
||||
Task<int> IRunner.RunAsync<TStack>() => RunAsync(() => new TStack());
|
||||
|
||||
public Task<int> RunAsync<TStack>(Func<TStack> stackFactory) where TStack : Stack
|
||||
{
|
||||
|
@ -60,7 +60,7 @@ namespace Pulumi
|
|||
return WhileRunningAsync();
|
||||
}
|
||||
|
||||
public Task<int> RunAsync(Func<Task<IDictionary<string, object?>>> func, StackOptions? options)
|
||||
Task<int> IRunner.RunAsync(Func<Task<IDictionary<string, object?>>> func, StackOptions? options)
|
||||
{
|
||||
var stack = new Stack(func, options);
|
||||
RegisterTask("User program code.", stack.Outputs.DataTask);
|
||||
|
@ -214,10 +214,9 @@ namespace Pulumi
|
|||
}
|
||||
else
|
||||
{
|
||||
var location = System.Reflection.Assembly.GetEntryAssembly()?.Location;
|
||||
await _deployment.Logger.ErrorAsync(
|
||||
$@"Running program '{location}' failed with an unhandled exception:
|
||||
{exception.ToString()}").ConfigureAwait(false);
|
||||
var location = Assembly.GetEntryAssembly()?.Location;
|
||||
await _deployment.Logger.ErrorAsync($@"Running program '{location}' failed with an unhandled exception:
|
||||
{exception}").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
_deployment.Serilogger.Debug("Wrote last error. Returning from program.");
|
||||
|
|
|
@ -7,6 +7,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Pulumi.Testing;
|
||||
using Pulumirpc;
|
||||
using Serilog;
|
||||
using Serilog.Events;
|
||||
|
||||
|
@ -30,7 +31,7 @@ namespace Pulumi
|
|||
/// </para>
|
||||
/// Importantly: Cloud resources cannot be created outside of the lambda passed to any of the
|
||||
/// <see cref="Deployment.RunAsync(Action)"/> overloads. Because cloud Resource construction is
|
||||
/// inherently asynchronous, the result of this function is a <see cref="Task{T}"/> which should
|
||||
/// inherently asynchronous, the result of this function is a <see cref="Task{TResult}"/> which should
|
||||
/// then be returned or awaited. This will ensure that any problems that are encountered during
|
||||
/// the running of the program are properly reported. Failure to do this may lead to the
|
||||
/// program ending early before all resources are properly registered.
|
||||
|
@ -38,7 +39,7 @@ namespace Pulumi
|
|||
public sealed partial class Deployment : IDeploymentInternal
|
||||
{
|
||||
private static readonly object _instanceLock = new object();
|
||||
private static AsyncLocal<DeploymentInstance?> _instance = new AsyncLocal<DeploymentInstance?>();
|
||||
private static readonly AsyncLocal<DeploymentInstance?> _instance = new AsyncLocal<DeploymentInstance?>();
|
||||
|
||||
/// <summary>
|
||||
/// The current running deployment instance. This is only available from inside the function
|
||||
|
@ -101,6 +102,7 @@ namespace Pulumi
|
|||
|
||||
private Deployment()
|
||||
{
|
||||
// ReSharper disable UnusedVariable
|
||||
var monitor = Environment.GetEnvironmentVariable("PULUMI_MONITOR");
|
||||
var engine = Environment.GetEnvironmentVariable("PULUMI_ENGINE");
|
||||
var project = Environment.GetEnvironmentVariable("PULUMI_PROJECT");
|
||||
|
@ -121,6 +123,7 @@ namespace Pulumi
|
|||
{
|
||||
throw new InvalidOperationException("Program run without the Pulumi engine available; re-run using the `pulumi` CLI");
|
||||
}
|
||||
// ReSharper restore UnusedVariable
|
||||
|
||||
_isDryRun = dryRunValue;
|
||||
_stackName = stack;
|
||||
|
@ -193,7 +196,7 @@ namespace Pulumi
|
|||
{
|
||||
if (!this._featureSupport.ContainsKey(feature))
|
||||
{
|
||||
var request = new Pulumirpc.SupportsFeatureRequest {Id = feature };
|
||||
var request = new SupportsFeatureRequest {Id = feature };
|
||||
var response = await this.Monitor.SupportsFeatureAsync(request).ConfigureAwait(false);
|
||||
this._featureSupport[feature] = response.HasSupport;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace Pulumi
|
|||
Log.Debug(label);
|
||||
|
||||
// Be resilient to misbehaving callers.
|
||||
// ReSharper disable once ConstantNullCoalescingCondition
|
||||
args ??= InvokeArgs.Empty;
|
||||
|
||||
// Wait for all values to be available, and then perform the RPC.
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2016-2021, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
@ -40,7 +39,7 @@ namespace Pulumi
|
|||
// Wait for the parent to complete.
|
||||
// If no parent was provided, parent to the root resource.
|
||||
LogExcessive($"Getting parent urn: t={type}, name={name}, custom={custom}, remote={remote}");
|
||||
var parentURN = options.Parent != null
|
||||
var parentUrn = options.Parent != null
|
||||
? await options.Parent.Urn.GetValueAsync().ConfigureAwait(false)
|
||||
: await GetRootResourceAsync(type).ConfigureAwait(false);
|
||||
LogExcessive($"Got parent urn: t={type}, name={name}, custom={custom}, remote={remote}");
|
||||
|
@ -53,25 +52,21 @@ namespace Pulumi
|
|||
}
|
||||
|
||||
var providerRefs = new Dictionary<string, string>();
|
||||
if (remote)
|
||||
if (remote && options is ComponentResourceOptions componentOpts)
|
||||
{
|
||||
var componentOpts = options as ComponentResourceOptions;
|
||||
if (componentOpts != null)
|
||||
// If only the Provider opt is set, move it to the Providers list for further processing.
|
||||
if (componentOpts.Provider != null && componentOpts.Providers.Count == 0)
|
||||
{
|
||||
// If only the Provider opt is set, move it to the Providers list for further processing.
|
||||
if (componentOpts.Provider != null && componentOpts.Providers.Count == 0)
|
||||
{
|
||||
componentOpts.Providers.Add(componentOpts.Provider);
|
||||
componentOpts.Provider = null;
|
||||
}
|
||||
componentOpts.Providers.Add(componentOpts.Provider);
|
||||
componentOpts.Provider = null;
|
||||
}
|
||||
|
||||
foreach (var provider in componentOpts.Providers)
|
||||
foreach (var provider in componentOpts.Providers)
|
||||
{
|
||||
var pref = await ProviderResource.RegisterAsync(provider).ConfigureAwait(false);
|
||||
if (pref != null)
|
||||
{
|
||||
var pref = await ProviderResource.RegisterAsync(provider).ConfigureAwait(false);
|
||||
if (pref != null)
|
||||
{
|
||||
providerRefs.Add(provider.Package, pref);
|
||||
}
|
||||
providerRefs.Add(provider.Package, pref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,16 +77,16 @@ namespace Pulumi
|
|||
// The list of all dependencies (implicit or explicit).
|
||||
var allDirectDependencies = new HashSet<Resource>(explicitDirectDependencies);
|
||||
|
||||
var allDirectDependencyURNs = await GetAllTransitivelyReferencedCustomResourceURNsAsync(explicitDirectDependencies).ConfigureAwait(false);
|
||||
var propertyToDirectDependencyURNs = new Dictionary<string, HashSet<string>>();
|
||||
var allDirectDependencyUrns = await GetAllTransitivelyReferencedCustomResourceUrnsAsync(explicitDirectDependencies).ConfigureAwait(false);
|
||||
var propertyToDirectDependencyUrns = new Dictionary<string, HashSet<string>>();
|
||||
|
||||
foreach (var (propertyName, directDependencies) in propertyToDirectDependencies)
|
||||
{
|
||||
allDirectDependencies.AddRange(directDependencies);
|
||||
|
||||
var urns = await GetAllTransitivelyReferencedCustomResourceURNsAsync(directDependencies).ConfigureAwait(false);
|
||||
allDirectDependencyURNs.AddRange(urns);
|
||||
propertyToDirectDependencyURNs[propertyName] = urns;
|
||||
var urns = await GetAllTransitivelyReferencedCustomResourceUrnsAsync(directDependencies).ConfigureAwait(false);
|
||||
allDirectDependencyUrns.AddRange(urns);
|
||||
propertyToDirectDependencyUrns[propertyName] = urns;
|
||||
}
|
||||
|
||||
// Wait for all aliases. Note that we use 'res._aliases' instead of 'options.aliases' as
|
||||
|
@ -111,11 +106,11 @@ namespace Pulumi
|
|||
|
||||
return new PrepareResult(
|
||||
serializedProps,
|
||||
parentURN ?? "",
|
||||
parentUrn ?? "",
|
||||
providerRef ?? "",
|
||||
providerRefs,
|
||||
allDirectDependencyURNs,
|
||||
propertyToDirectDependencyURNs,
|
||||
allDirectDependencyUrns,
|
||||
propertyToDirectDependencyUrns,
|
||||
aliases);
|
||||
|
||||
void LogExcessive(string message)
|
||||
|
@ -128,7 +123,7 @@ namespace Pulumi
|
|||
private static Task<ImmutableArray<Resource>> GatherExplicitDependenciesAsync(InputList<Resource> resources)
|
||||
=> resources.ToOutput().GetValueAsync();
|
||||
|
||||
private static async Task<HashSet<string>> GetAllTransitivelyReferencedCustomResourceURNsAsync(
|
||||
private static async Task<HashSet<string>> GetAllTransitivelyReferencedCustomResourceUrnsAsync(
|
||||
HashSet<Resource> resources)
|
||||
{
|
||||
// Go through 'resources', but transitively walk through **Component** resources,
|
||||
|
@ -190,24 +185,24 @@ namespace Pulumi
|
|||
}
|
||||
}
|
||||
|
||||
private struct PrepareResult
|
||||
private readonly struct PrepareResult
|
||||
{
|
||||
public readonly Struct SerializedProps;
|
||||
public readonly string ParentUrn;
|
||||
public readonly string ProviderRef;
|
||||
public readonly Dictionary<string, string> ProviderRefs;
|
||||
public readonly HashSet<string> AllDirectDependencyURNs;
|
||||
public readonly Dictionary<string, HashSet<string>> PropertyToDirectDependencyURNs;
|
||||
public readonly HashSet<string> AllDirectDependencyUrns;
|
||||
public readonly Dictionary<string, HashSet<string>> PropertyToDirectDependencyUrns;
|
||||
public readonly List<string> Aliases;
|
||||
|
||||
public PrepareResult(Struct serializedProps, string parentUrn, string providerRef, Dictionary<string, string> providerRefs, HashSet<string> allDirectDependencyURNs, Dictionary<string, HashSet<string>> propertyToDirectDependencyURNs, List<string> aliases)
|
||||
public PrepareResult(Struct serializedProps, string parentUrn, string providerRef, Dictionary<string, string> providerRefs, HashSet<string> allDirectDependencyUrns, Dictionary<string, HashSet<string>> propertyToDirectDependencyUrns, List<string> aliases)
|
||||
{
|
||||
SerializedProps = serializedProps;
|
||||
ParentUrn = parentUrn;
|
||||
ProviderRef = providerRef;
|
||||
ProviderRefs = providerRefs;
|
||||
AllDirectDependencyURNs = allDirectDependencyURNs;
|
||||
PropertyToDirectDependencyURNs = propertyToDirectDependencyURNs;
|
||||
AllDirectDependencyUrns = allDirectDependencyUrns;
|
||||
PropertyToDirectDependencyUrns = propertyToDirectDependencyUrns;
|
||||
Aliases = aliases;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,8 +90,9 @@ namespace Pulumi
|
|||
resource, remote, newDependency, args, options).ConfigureAwait(false);
|
||||
|
||||
completionSources[Constants.UrnPropertyName].SetStringValue(response.urn, isKnown: true);
|
||||
if (resource is CustomResource customResource)
|
||||
if (resource is CustomResource)
|
||||
{
|
||||
// ReSharper disable once ConstantNullCoalescingCondition
|
||||
var id = response.id ?? "";
|
||||
completionSources[Constants.IdPropertyName].SetStringValue(id, isKnown: id != "");
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
// Copyright 2016-2019, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Threading.Tasks;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Pulumi.Serialization;
|
||||
using Pulumirpc;
|
||||
|
||||
namespace Pulumi
|
||||
|
@ -22,7 +20,6 @@ namespace Pulumi
|
|||
var prepareResult = await this.PrepareResourceAsync(
|
||||
label, resource, custom: true, remote: false, args, options).ConfigureAwait(false);
|
||||
|
||||
var serializer = new Serializer(_excessiveDebugOutput);
|
||||
Log.Debug($"ReadResource RPC prepared: id={id}, t={type}, name={name}" +
|
||||
(_excessiveDebugOutput ? $", obj={prepareResult.SerializedProps}" : ""));
|
||||
|
||||
|
@ -35,12 +32,12 @@ namespace Pulumi
|
|||
Parent = prepareResult.ParentUrn,
|
||||
Provider = prepareResult.ProviderRef,
|
||||
Properties = prepareResult.SerializedProps,
|
||||
Version = options?.Version ?? "",
|
||||
Version = options.Version ?? "",
|
||||
AcceptSecrets = true,
|
||||
AcceptResources = !_disableResourceReferences,
|
||||
};
|
||||
|
||||
request.Dependencies.AddRange(prepareResult.AllDirectDependencyURNs);
|
||||
request.Dependencies.AddRange(prepareResult.AllDirectDependencyUrns);
|
||||
|
||||
// Now run the operation, serializing the invocation if necessary.
|
||||
var response = await this.Monitor.ReadResourceAsync(resource, request);
|
||||
|
|
|
@ -54,12 +54,12 @@ namespace Pulumi
|
|||
request.Provider = prepareResult.ProviderRef;
|
||||
request.Providers.Add(prepareResult.ProviderRefs);
|
||||
request.Aliases.AddRange(prepareResult.Aliases);
|
||||
request.Dependencies.AddRange(prepareResult.AllDirectDependencyURNs);
|
||||
request.Dependencies.AddRange(prepareResult.AllDirectDependencyUrns);
|
||||
|
||||
foreach (var (key, resourceURNs) in prepareResult.PropertyToDirectDependencyURNs)
|
||||
foreach (var (key, resourceUrns) in prepareResult.PropertyToDirectDependencyUrns)
|
||||
{
|
||||
var deps = new RegisterResourceRequest.Types.PropertyDependencies();
|
||||
deps.Urns.AddRange(resourceURNs);
|
||||
deps.Urns.AddRange(resourceUrns);
|
||||
request.PropertyDependencies.Add(key, deps);
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ namespace Pulumi
|
|||
var customOpts = options as CustomResourceOptions;
|
||||
var deleteBeforeReplace = customOpts?.DeleteBeforeReplace;
|
||||
|
||||
var request = new RegisterResourceRequest()
|
||||
var request = new RegisterResourceRequest
|
||||
{
|
||||
Type = type,
|
||||
Name = name,
|
||||
|
@ -113,7 +113,7 @@ namespace Pulumi
|
|||
// Simply put, we simply convert our ticks to the integral number of nanoseconds
|
||||
// corresponding to it. Since each tick is 100ns, this can trivialy be done just by
|
||||
// appending "00" to it.
|
||||
return timeSpan.Value.Ticks.ToString() + "00ns";
|
||||
return timeSpan.Value.Ticks + "00ns";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright 2016-2019, Pulumi Corporation
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Google.Protobuf;
|
||||
using Pulumirpc;
|
||||
|
@ -22,7 +21,7 @@ namespace Pulumi
|
|||
private async Task RegisterResourceOutputsAsync(
|
||||
Resource resource, Output<IDictionary<string, object?>> outputs)
|
||||
{
|
||||
var opLabel = $"monitor.registerResourceOutputs(...)";
|
||||
var opLabel = "monitor.registerResourceOutputs(...)";
|
||||
|
||||
// The registration could very well still be taking place, so we will need to wait for its URN.
|
||||
// Additionally, the output properties might have come from other resources, so we must await those too.
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace Pulumi
|
|||
public partial class Deployment
|
||||
{
|
||||
private Task<string>? _rootResource;
|
||||
private object _rootResourceLock = new object();
|
||||
private readonly object _rootResourceLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a root resource URN that will automatically become the default parent of all
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Pulumi
|
|||
public partial class Deployment
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="RunAsync(Func{Task{IDictionary{string, object}}}, StackOptions)"/> for more details.
|
||||
/// <see cref="RunAsync(Func{Task{IDictionary{string,object}}}, StackOptions)"/> for more details.
|
||||
/// </summary>
|
||||
/// <param name="action">Callback that creates stack resources.</param>
|
||||
public static Task<int> RunAsync(Action action)
|
||||
|
@ -174,7 +174,7 @@ namespace Pulumi
|
|||
return engine.Errors.Count switch
|
||||
{
|
||||
1 => throw new RunException(engine.Errors.Single()),
|
||||
int v when v > 1 => throw new AggregateException(engine.Errors.Select(e => new RunException(e))),
|
||||
var v when v > 1 => throw new AggregateException(engine.Errors.Select(e => new RunException(e))),
|
||||
_ => monitor.Resources.ToImmutableArray()
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright 2016-2019, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -65,7 +64,7 @@ namespace Pulumi
|
|||
propertyToDependentResources.ToImmutable());
|
||||
}
|
||||
|
||||
private struct SerializationResult
|
||||
private readonly struct SerializationResult
|
||||
{
|
||||
public readonly Struct Serialized;
|
||||
public readonly ImmutableDictionary<string, HashSet<Resource>> PropertyToDependentResources;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Grpc.Core;
|
||||
using Pulumirpc;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Grpc.Core;
|
||||
using Pulumirpc;
|
||||
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
namespace Pulumi
|
||||
{
|
||||
/// <summary>
|
||||
/// Options to help control the behavior of <see cref="IDeployment.InvokeAsync{T}(string,
|
||||
/// InvokeArgs, InvokeOptions)"/>.
|
||||
/// Options to help control the behavior of <see cref="IDeployment.InvokeAsync{T}(string, InvokeArgs, InvokeOptions)"/>.
|
||||
/// </summary>
|
||||
public class InvokeOptions
|
||||
{
|
||||
|
|
|
@ -12,8 +12,8 @@ namespace Pulumi
|
|||
/// </summary>
|
||||
public class ResourceException : Exception
|
||||
{
|
||||
internal readonly Resource? Resource;
|
||||
internal readonly bool HideStack;
|
||||
internal Resource? Resource { get; }
|
||||
internal bool HideStack { get; }
|
||||
|
||||
public ResourceException(string message, Resource? resource, bool hideStack = false) : base(message)
|
||||
{
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Pulumi
|
|||
return result;
|
||||
}
|
||||
|
||||
public static void Deconstruct<K, V>(this KeyValuePair<K, V> pair, out K key, out V value)
|
||||
public static void Deconstruct<TKey, TValue>(this KeyValuePair<TKey, TValue> pair, out TKey key, out TValue value)
|
||||
{
|
||||
key = pair.Key;
|
||||
value = pair.Value;
|
||||
|
@ -43,6 +43,7 @@ namespace Pulumi
|
|||
{
|
||||
_ = response.ContinueWith(t =>
|
||||
{
|
||||
// ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault
|
||||
switch (t.Status)
|
||||
{
|
||||
default: throw new InvalidOperationException("Task was not complete: " + t.Status);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2016-2019, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Pulumi
|
||||
|
@ -20,7 +19,7 @@ namespace Pulumi
|
|||
/// </summary>
|
||||
public List<ProviderResource> Providers
|
||||
{
|
||||
get => _providers ?? (_providers = new List<ProviderResource>());
|
||||
get => _providers ??= new List<ProviderResource>();
|
||||
set => _providers = value;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Pulumi
|
|||
/// </summary>
|
||||
public List<string> AdditionalSecretOutputs
|
||||
{
|
||||
get => _additionalSecretOutputs ?? (_additionalSecretOutputs = new List<string>());
|
||||
get => _additionalSecretOutputs ??= new List<string>();
|
||||
set => _additionalSecretOutputs = value;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,13 +16,13 @@ namespace Pulumi
|
|||
public DependencyProviderResource(string reference)
|
||||
: base(package: "", name: "", args: ResourceArgs.Empty, dependency: true)
|
||||
{
|
||||
int lastSep = reference.LastIndexOf("::", StringComparison.Ordinal);
|
||||
var lastSep = reference.LastIndexOf("::", StringComparison.Ordinal);
|
||||
if (lastSep == -1)
|
||||
{
|
||||
throw new ArgumentException($"Expected \"::\" in provider reference ${reference}.");
|
||||
}
|
||||
string urn = reference.Substring(0, lastSep);
|
||||
string id = reference.Substring(lastSep + 2);
|
||||
var urn = reference.Substring(0, lastSep);
|
||||
var id = reference.Substring(lastSep + 2);
|
||||
|
||||
var resources = ImmutableHashSet.Create<Resource>(this);
|
||||
|
||||
|
|
|
@ -35,14 +35,15 @@ namespace Pulumi
|
|||
|
||||
var all = fieldQuery.Concat(propQuery).ToList();
|
||||
|
||||
foreach (var (attr, memberName, memberType, getValue) in all)
|
||||
foreach (var (_, memberName, memberType, _) in all)
|
||||
{
|
||||
var fullName = $"[Input] {this.GetType().FullName}.{memberName}";
|
||||
// ReSharper disable once VirtualMemberCallInConstructor
|
||||
ValidateMember(memberType, fullName);
|
||||
}
|
||||
|
||||
_inputInfos = all.Select(t =>
|
||||
new InputInfo(t.attr, t.memberName, t.memberType, t.getValue)).ToImmutableArray();
|
||||
new InputInfo(t.attr!, t.memberName, t.memberType, t.getValue)).ToImmutableArray();
|
||||
}
|
||||
|
||||
internal virtual async Task<ImmutableDictionary<string, object?>> ToDictionaryAsync()
|
||||
|
@ -80,14 +81,15 @@ namespace Pulumi
|
|||
return JsonFormatter.Default.Format(value);
|
||||
}
|
||||
|
||||
private struct InputInfo
|
||||
private readonly struct InputInfo
|
||||
{
|
||||
public readonly InputAttribute Attribute;
|
||||
// ReSharper disable once NotAccessedField.Local
|
||||
public readonly Type MemberType;
|
||||
public readonly string MemberName;
|
||||
public Func<object, object?> GetValue;
|
||||
public readonly Func<object, object?> GetValue;
|
||||
|
||||
public InputInfo(InputAttribute attribute, string memberName, Type memberType, Func<object, object> getValue) : this()
|
||||
public InputInfo(InputAttribute attribute, string memberName, Type memberType, Func<object, object?> getValue) : this()
|
||||
{
|
||||
Attribute = attribute;
|
||||
MemberName = memberName;
|
||||
|
|
|
@ -11,10 +11,6 @@ namespace Pulumi
|
|||
{
|
||||
public static readonly InvokeArgs Empty = new EmptyInvokeArgs();
|
||||
|
||||
protected InvokeArgs()
|
||||
{
|
||||
}
|
||||
|
||||
private protected override void ValidateMember(Type memberType, string fullName)
|
||||
{
|
||||
if (typeof(IInput).IsAssignableFrom(memberType))
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Pulumi
|
|||
/// </summary>
|
||||
public class ProviderResource : CustomResource
|
||||
{
|
||||
internal readonly string Package;
|
||||
internal string Package { get; }
|
||||
|
||||
private string? _registrationId;
|
||||
|
||||
|
@ -53,14 +53,14 @@ namespace Pulumi
|
|||
|
||||
if (provider._registrationId == null)
|
||||
{
|
||||
var providerURN = await provider.Urn.GetValueAsync().ConfigureAwait(false);
|
||||
var providerID = await provider.Id.GetValueAsync().ConfigureAwait(false);
|
||||
if (string.IsNullOrEmpty(providerID))
|
||||
var providerUrn = await provider.Urn.GetValueAsync().ConfigureAwait(false);
|
||||
var providerId = await provider.Id.GetValueAsync().ConfigureAwait(false);
|
||||
if (string.IsNullOrEmpty(providerId))
|
||||
{
|
||||
providerID = Constants.UnknownValue;
|
||||
providerId = Constants.UnknownValue;
|
||||
}
|
||||
|
||||
provider._registrationId = $"{providerURN}::{providerID}";
|
||||
provider._registrationId = $"{providerUrn}::{providerId}";
|
||||
}
|
||||
|
||||
return provider._registrationId;
|
||||
|
|
|
@ -16,11 +16,6 @@ namespace Pulumi
|
|||
private readonly string _type;
|
||||
private readonly string _name;
|
||||
|
||||
/// <summary>
|
||||
/// The optional parent of this resource.
|
||||
/// </summary>
|
||||
private readonly Resource? _parentResource;
|
||||
|
||||
/// <summary>
|
||||
/// The child resources of this resource. We use these (only from a ComponentResource) to
|
||||
/// allow code to dependOn a ComponentResource and have that effectively mean that it is
|
||||
|
@ -56,7 +51,7 @@ namespace Pulumi
|
|||
/// ever need to reference the urn of a component resource. So it's acceptable if that sort
|
||||
/// of pattern failed in practice.
|
||||
/// </summary>
|
||||
internal readonly HashSet<Resource> ChildResources = new HashSet<Resource>();
|
||||
internal HashSet<Resource> ChildResources { get; } = new HashSet<Resource>();
|
||||
|
||||
/// <summary>
|
||||
/// Urn is the stable logical URN used to distinctly address a resource, both before and
|
||||
|
@ -187,14 +182,13 @@ namespace Pulumi
|
|||
|
||||
if (options.Parent != null)
|
||||
{
|
||||
this._parentResource = options.Parent;
|
||||
lock (this._parentResource.ChildResources)
|
||||
var parentResource = options.Parent;
|
||||
lock (parentResource.ChildResources)
|
||||
{
|
||||
this._parentResource.ChildResources.Add(this);
|
||||
parentResource.ChildResources.Add(this);
|
||||
}
|
||||
|
||||
if (options.Protect == null)
|
||||
options.Protect = options.Parent._protect;
|
||||
options.Protect ??= options.Parent._protect;
|
||||
|
||||
// Make a copy of the aliases array, and add to it any implicit aliases inherited from its parent
|
||||
options.Aliases = options.Aliases.ToList();
|
||||
|
@ -331,7 +325,6 @@ $"Only specify one of '{nameof(Alias.Parent)}', '{nameof(Alias.ParentUrn)}' or '
|
|||
if (value != null)
|
||||
{
|
||||
ThrowAliasPropertyConflict(name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,10 +11,6 @@ namespace Pulumi
|
|||
{
|
||||
public static readonly ResourceArgs Empty = new EmptyResourceArgs();
|
||||
|
||||
protected ResourceArgs()
|
||||
{
|
||||
}
|
||||
|
||||
private protected override void ValidateMember(Type memberType, string fullName)
|
||||
{
|
||||
// No validation. A member may or may not be IInput.
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Pulumi
|
|||
/// </summary>
|
||||
public InputList<Resource> DependsOn
|
||||
{
|
||||
get => _dependsOn ?? (_dependsOn = new InputList<Resource>());
|
||||
get => _dependsOn ??= new InputList<Resource>();
|
||||
set => _dependsOn = value;
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ namespace Pulumi
|
|||
/// </summary>
|
||||
public List<string> IgnoreChanges
|
||||
{
|
||||
get => _ignoreChanges ?? (_ignoreChanges = new List<string>());
|
||||
get => _ignoreChanges ??= new List<string>();
|
||||
set => _ignoreChanges = value;
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ namespace Pulumi
|
|||
/// </summary>
|
||||
public List<ResourceTransformation> ResourceTransformations
|
||||
{
|
||||
get => _resourceTransformations ?? (_resourceTransformations = new List<ResourceTransformation>());
|
||||
get => _resourceTransformations ??= new List<ResourceTransformation>();
|
||||
set => _resourceTransformations = value;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Threading.Tasks;
|
||||
using Pulumi.Serialization;
|
||||
|
||||
namespace Pulumi
|
||||
{
|
||||
|
@ -152,6 +151,6 @@ namespace Pulumi
|
|||
/// The name of the stack to reference.
|
||||
/// </summary>
|
||||
[Input("name", required: true)]
|
||||
public Input<string>? Name { get; set; } = null!;
|
||||
public Input<string>? Name { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,10 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Enum = System.Enum;
|
||||
using Type = System.Type;
|
||||
|
||||
// ReSharper disable TailRecursiveCall
|
||||
|
||||
namespace Pulumi.Serialization
|
||||
{
|
||||
|
@ -19,15 +23,15 @@ namespace Pulumi.Serialization
|
|||
return new OutputData<T>(ImmutableHashSet<Resource>.Empty, (T)data!, isKnown, isSecret);
|
||||
}
|
||||
|
||||
public static OutputData<object?> ConvertValue(string context, Value value, System.Type targetType)
|
||||
public static OutputData<object?> ConvertValue(string context, Value value, Type targetType)
|
||||
{
|
||||
return ConvertValue(context, value, targetType, ImmutableHashSet<Resource>.Empty);
|
||||
}
|
||||
|
||||
public static OutputData<object?> ConvertValue(
|
||||
string context, Value value, System.Type targetType, ImmutableHashSet<Resource> resources)
|
||||
string context, Value value, Type targetType, ImmutableHashSet<Resource> resources)
|
||||
{
|
||||
CheckTargetType(context, targetType, new HashSet<System.Type>());
|
||||
CheckTargetType(context, targetType, new HashSet<Type>());
|
||||
|
||||
var (deserialized, isKnown, isSecret) = Deserializer.Deserialize(value);
|
||||
var converted = ConvertObject(context, deserialized, targetType);
|
||||
|
@ -35,7 +39,7 @@ namespace Pulumi.Serialization
|
|||
return new OutputData<object?>(resources, converted, isKnown, isSecret);
|
||||
}
|
||||
|
||||
private static object? ConvertObject(string context, object? val, System.Type targetType)
|
||||
private static object? ConvertObject(string context, object? val, Type targetType)
|
||||
{
|
||||
var (result, exception) = TryConvertObject(context, val, targetType);
|
||||
if (exception != null)
|
||||
|
@ -44,7 +48,7 @@ namespace Pulumi.Serialization
|
|||
return result;
|
||||
}
|
||||
|
||||
private static (object?, InvalidOperationException?) TryConvertObject(string context, object? val, System.Type targetType)
|
||||
private static (object?, InvalidOperationException?) TryConvertObject(string context, object? val, Type targetType)
|
||||
{
|
||||
var targetIsNullable = targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable<>);
|
||||
|
||||
|
@ -116,7 +120,7 @@ namespace Pulumi.Serialization
|
|||
if (exception != null || value is null)
|
||||
return (null, exception);
|
||||
|
||||
return (System.Enum.ToObject(targetType, value), null);
|
||||
return (Enum.ToObject(targetType, value), null);
|
||||
}
|
||||
|
||||
if (targetType.IsValueType && targetType.GetCustomAttribute<EnumTypeAttribute>() != null)
|
||||
|
@ -136,7 +140,7 @@ namespace Pulumi.Serialization
|
|||
return (null, new InvalidOperationException(
|
||||
$"Expected target type {targetType.FullName} to have a constructor with a single {valType.FullName} parameter."));
|
||||
}
|
||||
return (enumTypeConstructor.Invoke(new object[] { val }), null);
|
||||
return (enumTypeConstructor.Invoke(new[] { val }), null);
|
||||
}
|
||||
|
||||
if (targetType.IsConstructedGenericType)
|
||||
|
@ -154,14 +158,14 @@ namespace Pulumi.Serialization
|
|||
$"Unexpected generic target type {targetType.FullName} when deserializing {context}");
|
||||
}
|
||||
|
||||
if (targetType.GetCustomAttribute<Pulumi.OutputTypeAttribute>() == null)
|
||||
if (targetType.GetCustomAttribute<OutputTypeAttribute>() == null)
|
||||
return (null, new InvalidOperationException(
|
||||
$"Unexpected target type {targetType.FullName} when deserializing {context}"));
|
||||
|
||||
var constructor = GetPropertyConstructor(targetType);
|
||||
if (constructor == null)
|
||||
return (null, new InvalidOperationException(
|
||||
$"Expected target type {targetType.FullName} to have [{nameof(Pulumi.OutputConstructorAttribute)}] constructor when deserializing {context}"));
|
||||
$"Expected target type {targetType.FullName} to have [{nameof(OutputConstructorAttribute)}] constructor when deserializing {context}"));
|
||||
|
||||
var (dictionary, tempException) = TryEnsureType<ImmutableDictionary<string, object>>(context, val);
|
||||
if (tempException != null)
|
||||
|
@ -191,20 +195,18 @@ namespace Pulumi.Serialization
|
|||
private static (object?, InvalidOperationException?) TryConvertJsonElement(
|
||||
string context, object val)
|
||||
{
|
||||
using (var stream = new MemoryStream())
|
||||
using var stream = new MemoryStream();
|
||||
using (var writer = new Utf8JsonWriter(stream))
|
||||
{
|
||||
using (var writer = new Utf8JsonWriter(stream))
|
||||
{
|
||||
var exception = TryWriteJson(context, writer, val);
|
||||
if (exception != null)
|
||||
return (null, exception);
|
||||
}
|
||||
|
||||
stream.Position = 0;
|
||||
var document = JsonDocument.Parse(stream);
|
||||
var element = document.RootElement;
|
||||
return (element, null);
|
||||
var exception = TryWriteJson(context, writer, val);
|
||||
if (exception != null)
|
||||
return (null, exception);
|
||||
}
|
||||
|
||||
stream.Position = 0;
|
||||
var document = JsonDocument.Parse(stream);
|
||||
var element = document.RootElement;
|
||||
return (element, null);
|
||||
}
|
||||
|
||||
private static InvalidOperationException? TryWriteJson(string context, Utf8JsonWriter writer, object? val)
|
||||
|
@ -252,7 +254,7 @@ namespace Pulumi.Serialization
|
|||
private static (T, InvalidOperationException?) TryEnsureType<T>(string context, object val)
|
||||
=> val is T t ? (t, null) : (default(T)!, new InvalidOperationException($"Expected {typeof(T).FullName} but got {val.GetType().FullName} deserializing {context}"));
|
||||
|
||||
private static (object?, InvalidOperationException?) TryConvertOneOf(string context, object val, System.Type oneOfType)
|
||||
private static (object?, InvalidOperationException?) TryConvertOneOf(string context, object val, Type oneOfType)
|
||||
{
|
||||
var firstType = oneOfType.GenericTypeArguments[0];
|
||||
var secondType = oneOfType.GenericTypeArguments[1];
|
||||
|
@ -275,14 +277,14 @@ namespace Pulumi.Serialization
|
|||
}
|
||||
|
||||
private static (object?, InvalidOperationException?) TryConvertArray(
|
||||
string fieldName, object val, System.Type targetType)
|
||||
string fieldName, object val, Type targetType)
|
||||
{
|
||||
if (!(val is ImmutableArray<object> array))
|
||||
return (null, new InvalidOperationException(
|
||||
$"Expected {typeof(ImmutableArray<object>).FullName} but got {val.GetType().FullName} deserializing {fieldName}"));
|
||||
|
||||
var builder =
|
||||
typeof(ImmutableArray).GetMethod(nameof(ImmutableArray.CreateBuilder), Array.Empty<System.Type>())!
|
||||
typeof(ImmutableArray).GetMethod(nameof(ImmutableArray.CreateBuilder), Array.Empty<Type>())!
|
||||
.MakeGenericMethod(targetType.GenericTypeArguments)
|
||||
.Invoke(obj: null, parameters: null)!;
|
||||
|
||||
|
@ -303,7 +305,7 @@ namespace Pulumi.Serialization
|
|||
}
|
||||
|
||||
private static (object?, InvalidOperationException?) TryConvertDictionary(
|
||||
string fieldName, object val, System.Type targetType)
|
||||
string fieldName, object val, Type targetType)
|
||||
{
|
||||
if (!(val is ImmutableDictionary<string, object> dictionary))
|
||||
return (null, new InvalidOperationException(
|
||||
|
@ -319,7 +321,7 @@ namespace Pulumi.Serialization
|
|||
$"Unexpected type {targetType.FullName} when deserializing {fieldName}. ImmutableDictionary's TKey type was not {typeof(string).FullName}"));
|
||||
|
||||
var builder =
|
||||
typeof(ImmutableDictionary).GetMethod(nameof(ImmutableDictionary.CreateBuilder), Array.Empty<System.Type>())!
|
||||
typeof(ImmutableDictionary).GetMethod(nameof(ImmutableDictionary.CreateBuilder), Array.Empty<Type>())!
|
||||
.MakeGenericMethod(targetType.GenericTypeArguments)
|
||||
.Invoke(obj: null, parameters: null)!;
|
||||
|
||||
|
@ -341,7 +343,7 @@ namespace Pulumi.Serialization
|
|||
return (builderToImmutable.Invoke(builder, null), null);
|
||||
}
|
||||
|
||||
public static void CheckTargetType(string context, System.Type targetType, HashSet<System.Type> seenTypes)
|
||||
public static void CheckTargetType(string context, Type targetType, HashSet<Type> seenTypes)
|
||||
{
|
||||
// types can be recursive. So only dive into a type if it's the first time we're seeing it.
|
||||
if (!seenTypes.Add(targetType))
|
||||
|
@ -398,7 +400,7 @@ namespace Pulumi.Serialization
|
|||
throw new InvalidOperationException(
|
||||
$"{targetType.FullName} had [{nameof(EnumTypeAttribute)}], but did not contain constructor with a single String or Double parameter.");
|
||||
|
||||
static bool CheckEnumType(System.Type targetType, System.Type underlyingType)
|
||||
static bool CheckEnumType(Type targetType, Type underlyingType)
|
||||
{
|
||||
var constructor = targetType.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { underlyingType }, null);
|
||||
if (constructor == null)
|
||||
|
@ -424,39 +426,34 @@ namespace Pulumi.Serialization
|
|||
CheckTargetType(context, targetType.GenericTypeArguments.Single(), seenTypes);
|
||||
return;
|
||||
}
|
||||
else if (targetType.GetGenericTypeDefinition() == typeof(Union<,>))
|
||||
if (targetType.GetGenericTypeDefinition() == typeof(Union<,>))
|
||||
{
|
||||
CheckTargetType(context, targetType.GenericTypeArguments[0], seenTypes);
|
||||
CheckTargetType(context, targetType.GenericTypeArguments[1], seenTypes);
|
||||
return;
|
||||
}
|
||||
else if (targetType.GetGenericTypeDefinition() == typeof(ImmutableArray<>))
|
||||
if (targetType.GetGenericTypeDefinition() == typeof(ImmutableArray<>))
|
||||
{
|
||||
CheckTargetType(context, targetType.GenericTypeArguments.Single(), seenTypes);
|
||||
return;
|
||||
}
|
||||
else if (targetType.GetGenericTypeDefinition() == typeof(ImmutableDictionary<,>))
|
||||
if (targetType.GetGenericTypeDefinition() == typeof(ImmutableDictionary<,>))
|
||||
{
|
||||
var dictTypeArgs = targetType.GenericTypeArguments;
|
||||
if (dictTypeArgs[0] != typeof(string))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$@"{context} contains invalid type {targetType.FullName}:
|
||||
throw new InvalidOperationException($@"{context} contains invalid type {targetType.FullName}:
|
||||
The only allowed ImmutableDictionary 'TKey' type is 'String'.");
|
||||
}
|
||||
|
||||
CheckTargetType(context, dictTypeArgs[1], seenTypes);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$@"{context} contains invalid type {targetType.FullName}:
|
||||
throw new InvalidOperationException($@"{context} contains invalid type {targetType.FullName}:
|
||||
The only generic types allowed are ImmutableArray<...> and ImmutableDictionary<string, ...>");
|
||||
}
|
||||
}
|
||||
|
||||
var propertyTypeAttribute = (Attribute?)targetType.GetCustomAttribute<OutputTypeAttribute>();
|
||||
var propertyTypeAttribute = targetType.GetCustomAttribute<OutputTypeAttribute>();
|
||||
if (propertyTypeAttribute == null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
|
@ -479,8 +476,8 @@ $@"{targetType.FullName} had [{nameof(OutputTypeAttribute)}], but did not contai
|
|||
}
|
||||
}
|
||||
|
||||
private static ConstructorInfo GetPropertyConstructor(System.Type outputTypeArg)
|
||||
private static ConstructorInfo? GetPropertyConstructor(Type outputTypeArg)
|
||||
=> outputTypeArg.GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(
|
||||
c => c.GetCustomAttributes<OutputConstructorAttribute>() != null);
|
||||
c => c.GetCustomAttribute<OutputConstructorAttribute>() != null);
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue