Simplify resource options (#3943)

Simplify resource options, making the base class abstract
This commit is contained in:
Mikhail Shilkov 2020-02-21 09:24:52 +01:00 committed by GitHub
parent 259b2d314a
commit 42d1a606a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 117 additions and 154 deletions

View file

@ -23,6 +23,9 @@ CHANGELOG
- Disable interactive progress display when no terminal size is available.
[#3936](https://github.com/pulumi/pulumi/pull/3936)
- Mark `ResourceOptions` class as abstract in the .NET SDK. Require the use of derived classes.
[#3943](https://github.com/pulumi/pulumi/pull/3943)
## 1.10.1 (2020-02-06)
- Support stack references in the Go SDK.
[#3829](https://github.com/pulumi/pulumi/pull/3829)

View file

@ -22,7 +22,7 @@ Pulumi.AssetArchive
Pulumi.AssetArchive.AssetArchive(System.Collections.Generic.IDictionary<string, Pulumi.AssetOrArchive> assets) -> void
Pulumi.AssetOrArchive
Pulumi.ComponentResource
Pulumi.ComponentResource.ComponentResource(string type, string name, Pulumi.ResourceOptions options = null) -> void
Pulumi.ComponentResource.ComponentResource(string type, string name, Pulumi.ComponentResourceOptions options = null) -> void
Pulumi.ComponentResource.RegisterOutputs() -> void
Pulumi.ComponentResource.RegisterOutputs(Pulumi.Output<System.Collections.Generic.IDictionary<string, object>> outputs) -> void
Pulumi.ComponentResource.RegisterOutputs(System.Collections.Generic.IDictionary<string, object> outputs) -> void
@ -50,7 +50,7 @@ Pulumi.Config.RequireSecretBoolean(string key) -> Pulumi.Output<bool>
Pulumi.Config.RequireSecretInt32(string key) -> Pulumi.Output<int>
Pulumi.Config.RequireSecretObject<T>(string key) -> Pulumi.Output<T>
Pulumi.CustomResource
Pulumi.CustomResource.CustomResource(string type, string name, Pulumi.ResourceArgs args, Pulumi.ResourceOptions options = null) -> void
Pulumi.CustomResource.CustomResource(string type, string name, Pulumi.ResourceArgs args, Pulumi.CustomResourceOptions options = null) -> void
Pulumi.CustomResource.Id.get -> Pulumi.Output<string>
Pulumi.CustomResourceOptions
Pulumi.CustomResourceOptions.AdditionalSecretOutputs.get -> System.Collections.Generic.List<string>
@ -127,7 +127,7 @@ Pulumi.OutputTypeAttribute
Pulumi.OutputTypeAttribute.OutputTypeAttribute() -> void
Pulumi.OutputExtensions
Pulumi.ProviderResource
Pulumi.ProviderResource.ProviderResource(string package, string name, Pulumi.ResourceArgs args, Pulumi.ResourceOptions options = null) -> void
Pulumi.ProviderResource.ProviderResource(string package, string name, Pulumi.ResourceArgs args, Pulumi.CustomResourceOptions options = null) -> void
Pulumi.RemoteArchive
Pulumi.RemoteArchive.RemoteArchive(string uri) -> void
Pulumi.RemoteAsset
@ -191,7 +191,7 @@ Pulumi.StackReference.Outputs.get -> Pulumi.Output<System.Collections.Immutable.
Pulumi.StackReference.RequireOutput(Pulumi.Input<string> name) -> Pulumi.Output<object>
Pulumi.StackReference.RequireValueAsync(Pulumi.Input<string> name) -> System.Threading.Tasks.Task<object>
Pulumi.StackReference.SecretOutputNames.get -> Pulumi.Output<System.Collections.Immutable.ImmutableArray<string>>
Pulumi.StackReference.StackReference(string name, Pulumi.StackReferenceArgs args = null, Pulumi.ResourceOptions options = null) -> void
Pulumi.StackReference.StackReference(string name, Pulumi.StackReferenceArgs args = null, Pulumi.CustomResourceOptions options = null) -> void
Pulumi.StackReferenceArgs
Pulumi.StackReferenceArgs.Name.get -> Pulumi.Input<string>
Pulumi.StackReferenceArgs.Name.set -> void
@ -216,8 +216,8 @@ Pulumi.Utilities.OutputUtilities
override Pulumi.Union<T0, T1>.Equals(object obj) -> bool
override Pulumi.Union<T0, T1>.GetHashCode() -> int
override Pulumi.Union<T0, T1>.ToString() -> string
static Pulumi.ComponentResourceOptions.Merge(Pulumi.ResourceOptions options1, Pulumi.ResourceOptions options2) -> Pulumi.ComponentResourceOptions
static Pulumi.CustomResourceOptions.Merge(Pulumi.ResourceOptions options1, Pulumi.ResourceOptions options2) -> Pulumi.CustomResourceOptions
static Pulumi.ComponentResourceOptions.Merge(Pulumi.ComponentResourceOptions options1, Pulumi.ComponentResourceOptions options2) -> Pulumi.ComponentResourceOptions
static Pulumi.CustomResourceOptions.Merge(Pulumi.CustomResourceOptions options1, Pulumi.CustomResourceOptions options2) -> Pulumi.CustomResourceOptions
static Pulumi.Deployment.Instance.get -> Pulumi.IDeployment
static Pulumi.Deployment.RunAsync(System.Action action) -> System.Threading.Tasks.Task<int>
static Pulumi.Deployment.RunAsync(System.Func<System.Collections.Generic.IDictionary<string, object>> func) -> System.Threading.Tasks.Task<int>
@ -300,7 +300,6 @@ static Pulumi.OutputExtensions.Length<T>(this Pulumi.Output<System.Collections.I
static Pulumi.OutputExtensions.Value<T0, T1>(this Pulumi.Output<Pulumi.Union<T0, T1>> output) -> Pulumi.Output<object>
static Pulumi.Utilities.OutputUtilities.GetDependenciesAsync<T>(Pulumi.Output<T> output) -> System.Threading.Tasks.Task<System.Collections.Immutable.ImmutableHashSet<Pulumi.Resource>>
static Pulumi.Utilities.OutputUtilities.GetIsKnownAsync<T>(Pulumi.Output<T> output) -> System.Threading.Tasks.Task<bool>
static Pulumi.ResourceOptions.Merge(Pulumi.ResourceOptions options1, Pulumi.ResourceOptions options2) -> Pulumi.ResourceOptions
static Pulumi.Union<T0, T1>.FromT0(T0 input) -> Pulumi.Union<T0, T1>
static Pulumi.Union<T0, T1>.FromT1(T1 input) -> Pulumi.Union<T0, T1>
static Pulumi.Union<T0, T1>.implicit operator Pulumi.Union<T0, T1>(T0 t) -> Pulumi.Union<T0, T1>

View file

@ -22,7 +22,7 @@ namespace Pulumi
/// this resource depends on, controlling the order in which we perform resource operations.
/// </summary>
#pragma warning disable RS0022 // Constructor make noninheritable base class inheritable
public ComponentResource(string type, string name, ResourceOptions? options = null)
public ComponentResource(string type, string name, ComponentResourceOptions? options = null)
: base(type, name, custom: false,
args: ResourceArgs.Empty,
options ?? new ComponentResourceOptions())

View file

@ -1,6 +1,6 @@
// Copyright 2016-2019, Pulumi Corporation
using System;
using System;
using System.Collections.Generic;
namespace Pulumi
@ -26,16 +26,60 @@ namespace Pulumi
internal override ResourceOptions Clone()
=> CreateComponentResourceOptionsCopy(this);
/// <inheritdoc cref="ResourceOptions.Merge(ResourceOptions, ResourceOptions)"/>
public static new ComponentResourceOptions Merge(ResourceOptions? options1, ResourceOptions? options2)
/// <summary>
/// Takes two <see cref="ComponentResourceOptions"/> values and produces a new
/// <see cref="ComponentResourceOptions"/> with the respective
/// properties of <paramref name="options2"/> merged over the same properties in <paramref
/// name="options1"/>. The original options objects will be unchanged.
/// <para/>
/// A new instance will always be returned.
/// <para/>
/// Conceptually property merging follows these basic rules:
/// <list type="number">
/// <item>
/// If the property is a collection, the final value will be a collection containing the
/// values from each options object.
/// </item>
/// <item>
/// Simple scalar values from <paramref name="options2"/> (i.e. <see cref="string"/>s,
/// <see cref="int"/>s, <see cref="bool"/>s) will replace the values of <paramref
/// name="options1"/>.
/// </item>
/// <item>
/// <see langword="null"/> values in <paramref name="options2"/> will be ignored.
/// </item>
/// </list>
/// </summary>
public static ComponentResourceOptions Merge(ComponentResourceOptions? options1, ComponentResourceOptions? options2)
{
if (options1 is CustomResourceOptions || options2 is CustomResourceOptions)
throw new ArgumentException($"{nameof(ComponentResourceOptions)}.{nameof(Merge)} cannot be used to merge {nameof(CustomResourceOptions)}");
options1 = options1 != null ? CreateComponentResourceOptionsCopy(options1) : new ComponentResourceOptions();
options2 = options2 != null ? CreateComponentResourceOptionsCopy(options2) : new ComponentResourceOptions();
return (ComponentResourceOptions)ResourceOptions.Merge(
CreateComponentResourceOptionsCopy(options1),
CreateComponentResourceOptionsCopy(options2));
ExpandProviders(options1);
ExpandProviders(options2);
// first, merge all the normal option values over
MergeNormalOptions(options1, options2);
options1.Providers.AddRange(options2.Providers);
if (options1.Providers.Count == 1)
{
options1.Provider = options1.Providers[0];
options1.Providers.Clear();
}
return options1;
static void ExpandProviders(ComponentResourceOptions options)
{
if (options.Provider != null)
{
options.Providers = new List<ProviderResource> { options.Provider };
options.Provider = null;
}
}
}
}
}

View file

@ -30,14 +30,10 @@ namespace Pulumi
/// current known resource state.
/// </summary>
#pragma warning disable RS0022 // Constructor make noninheritable base class inheritable
public CustomResource(string type, string name, ResourceArgs? args, ResourceOptions? options = null)
: base(type, name, custom: true, args ?? ResourceArgs.Empty, options ?? new ResourceOptions())
public CustomResource(string type, string name, ResourceArgs? args, CustomResourceOptions? options = null)
: base(type, name, custom: true, args ?? ResourceArgs.Empty, options ?? new CustomResourceOptions())
#pragma warning restore RS0022 // Constructor make noninheritable base class inheritable
{
if (options is ComponentResourceOptions componentOpts && componentOpts.Providers != null)
{
throw new ResourceException("Do not supply 'providers' option to a CustomResource. Did you mean 'provider' instead?", this);
}
}
}
}

View file

@ -1,6 +1,5 @@
// Copyright 2016-2019, Pulumi Corporation
using System;
using System.Collections.Generic;
namespace Pulumi
@ -42,15 +41,43 @@ namespace Pulumi
internal override ResourceOptions Clone()
=> CreateCustomResourceOptionsCopy(this);
/// <inheritdoc cref="ResourceOptions.Merge(ResourceOptions, ResourceOptions)"/>
public static new CustomResourceOptions Merge(ResourceOptions? options1, ResourceOptions? options2)
/// <summary>
/// Takes two <see cref="CustomResourceOptions"/> values and produces a new
/// <see cref="CustomResourceOptions"/> with the respective
/// properties of <paramref name="options2"/> merged over the same properties in <paramref
/// name="options1"/>. The original options objects will be unchanged.
/// <para/>
/// A new instance will always be returned.
/// <para/>
/// Conceptually property merging follows these basic rules:
/// <list type="number">
/// <item>
/// If the property is a collection, the final value will be a collection containing the
/// values from each options object.
/// </item>
/// <item>
/// Simple scalar values from <paramref name="options2"/> (i.e. <see cref="string"/>s,
/// <see cref="int"/>s, <see cref="bool"/>s) will replace the values of <paramref
/// name="options1"/>.
/// </item>
/// <item>
/// <see langword="null"/> values in <paramref name="options2"/> will be ignored.
/// </item>
/// </list>
/// </summary>
public static CustomResourceOptions Merge(CustomResourceOptions? options1, CustomResourceOptions? options2)
{
if (options1 is ComponentResourceOptions || options2 is ComponentResourceOptions)
throw new ArgumentException($"{nameof(CustomResourceOptions)}.{nameof(Merge)} cannot be used to merge {nameof(ComponentResourceOptions)}");
options1 = options1 != null ? CreateCustomResourceOptionsCopy(options1) : new CustomResourceOptions();
options2 = options2 != null ? CreateCustomResourceOptionsCopy(options2) : new CustomResourceOptions();
return (CustomResourceOptions)ResourceOptions.Merge(
CreateCustomResourceOptionsCopy(options1),
CreateCustomResourceOptionsCopy(options2));
// first, merge all the normal option values over
MergeNormalOptions(options1, options2);
options1.DeleteBeforeReplace = options2.DeleteBeforeReplace ?? options1.DeleteBeforeReplace;
options1.ImportId = options2.ImportId ?? options1.ImportId;
options1.AdditionalSecretOutputs.AddRange(options2.AdditionalSecretOutputs);
return options1;
}
}
}

View file

@ -21,7 +21,7 @@ namespace Pulumi
/// </summary>
public ProviderResource(
string package, string name,
ResourceArgs args, ResourceOptions? options = null)
ResourceArgs args, CustomResourceOptions? options = null)
: base($"pulumi:providers:{package}", name, args, options)
{
this.Package = package;

View file

@ -7,7 +7,7 @@ namespace Pulumi
/// <summary>
/// ResourceOptions is a bag of optional settings that control a resource's behavior.
/// </summary>
public partial class ResourceOptions
public abstract partial class ResourceOptions
{
/// <summary>
/// An optional existing ID to load, rather than create.
@ -87,7 +87,6 @@ namespace Pulumi
/// </summary>
public List<Input<Alias>> Aliases { get; set; } = new List<Input<Alias>>();
internal virtual ResourceOptions Clone()
=> CreateResourceOptionsCopy(this);
internal abstract ResourceOptions Clone();
}
}

View file

@ -22,12 +22,9 @@ namespace Pulumi
Version = options.Version
};
internal static ResourceOptions CreateResourceOptionsCopy(ResourceOptions options)
=> CreateCopy<ResourceOptions>(options);
internal static CustomResourceOptions CreateCustomResourceOptionsCopy(ResourceOptions? options)
{
var copy = CreateCopy<CustomResourceOptions>(options ?? new ResourceOptions());
var copy = CreateCopy<CustomResourceOptions>(options ?? new CustomResourceOptions());
var customOptions = options as CustomResourceOptions;
copy.AdditionalSecretOutputs = customOptions?.AdditionalSecretOutputs.ToList() ?? new List<string>();
@ -39,7 +36,7 @@ namespace Pulumi
internal static ComponentResourceOptions CreateComponentResourceOptionsCopy(ResourceOptions? options)
{
var copy = CreateCopy<ComponentResourceOptions>(options ?? new ResourceOptions());
var copy = CreateCopy<ComponentResourceOptions>(options ?? new ComponentResourceOptions());
var componentOptions = options as ComponentResourceOptions;
copy.Providers = componentOptions?.Providers.ToList() ?? new List<ProviderResource>();

View file

@ -1,125 +1,23 @@
// Copyright 2016-2019, Pulumi Corporation
using System;
using System.Collections.Generic;
namespace Pulumi
{
public partial class ResourceOptions
{
/// <summary>
/// Takes two ResourceOptions values and produces a new ResourceOptions with the respective
/// properties of <paramref name="options2"/> merged over the same properties in <paramref
/// name="options1"/>. The original options objects will be unchanged.
/// <para/>
/// A new instance will always be returned.
/// <para/>
/// Conceptually property merging follows these basic rules:
/// <list type="number">
/// <item>
/// If the property is a collection, the final value will be a collection containing the
/// values from each options object.
/// </item>
/// <item>
/// Simple scaler values from <paramref name="options2"/> (i.e. <see cref="string"/>s,
/// <see cref="int"/>s, <see cref="bool"/>s) will replace the values of <paramref
/// name="options1"/>.
/// </item>
/// <item>
/// <see langword="null"/> values in <paramref name="options2"/> will be ignored.
/// </item>
/// </list>
/// </summary>
public static ResourceOptions Merge(ResourceOptions? options1, ResourceOptions? options2)
internal static void MergeNormalOptions(ResourceOptions options1, ResourceOptions options2)
{
options1 ??= new ResourceOptions();
options2 ??= new ResourceOptions();
options1.Id = options2.Id ?? options1.Id;
options1.Parent = options2.Parent ?? options1.Parent;
options1.Protect = options2.Protect ?? options1.Protect;
options1.Version = options2.Version ?? options1.Version;
options1.Provider = options2.Provider ?? options1.Provider;
options1.CustomTimeouts = options2.CustomTimeouts ?? options1.CustomTimeouts;
if ((options1 is CustomResourceOptions && options2 is ComponentResourceOptions) ||
(options1 is ComponentResourceOptions && options2 is CustomResourceOptions))
{
throw new ArgumentException(
$"Cannot merge a {nameof(CustomResourceOptions)} and {nameof(ComponentResourceOptions)} together.");
}
// make an appropriate copy of both options bag, then the copy of options2 into the copy
// of options1 and return the copy of options1.
if (options1 is CustomResourceOptions || options2 is CustomResourceOptions)
{
return MergeCustomOptions(
CreateCustomResourceOptionsCopy(options1),
CreateCustomResourceOptionsCopy(options2));
}
else if (options1 is ComponentResourceOptions || options2 is ComponentResourceOptions)
{
return MergeComponentOptions(
CreateComponentResourceOptionsCopy(options1),
CreateComponentResourceOptionsCopy(options2));
}
else
{
return MergeNormalOptions(
CreateResourceOptionsCopy(options1),
CreateResourceOptionsCopy(options2));
}
static ResourceOptions MergeNormalOptions(ResourceOptions options1, ResourceOptions options2)
{
options1.Id = options2.Id ?? options1.Id;
options1.Parent = options2.Parent ?? options1.Parent;
options1.Protect = options2.Protect ?? options1.Protect;
options1.Version = options2.Version ?? options1.Version;
options1.Provider = options2.Provider ?? options1.Provider;
options1.CustomTimeouts = options2.CustomTimeouts ?? options1.CustomTimeouts;
options1.IgnoreChanges.AddRange(options2.IgnoreChanges);
options1.ResourceTransformations.AddRange(options2.ResourceTransformations);
options1.Aliases.AddRange(options2.Aliases);
options1.IgnoreChanges.AddRange(options2.IgnoreChanges);
options1.ResourceTransformations.AddRange(options2.ResourceTransformations);
options1.Aliases.AddRange(options2.Aliases);
options1.DependsOn = options1.DependsOn.Concat(options2.DependsOn);
return options1;
}
static CustomResourceOptions MergeCustomOptions(CustomResourceOptions options1, CustomResourceOptions options2)
{
// first, merge all the normal option values over
MergeNormalOptions(options1, options2);
options1.DeleteBeforeReplace = options2.DeleteBeforeReplace ?? options1.DeleteBeforeReplace;
options1.ImportId = options2.ImportId ?? options1.ImportId;
options1.AdditionalSecretOutputs.AddRange(options2.AdditionalSecretOutputs);
return options1;
}
static ComponentResourceOptions MergeComponentOptions(ComponentResourceOptions options1, ComponentResourceOptions options2)
{
ExpandProviders(options1);
ExpandProviders(options2);
// first, merge all the normal option values over
MergeNormalOptions(options1, options2);
options1.Providers.AddRange(options2.Providers);
if (options1.Providers.Count == 1)
{
options1.Provider = options1.Providers[0];
options1.Providers.Clear();
}
return options1;
}
static void ExpandProviders(ComponentResourceOptions options)
{
if (options.Provider != null)
{
options.Providers = new List<ProviderResource> { options.Provider };
options.Provider = null;
}
}
options1.DependsOn = options1.DependsOn.Concat(options2.DependsOn);
}
}
}

View file

@ -39,7 +39,7 @@ namespace Pulumi
/// <param name="name">The unique name of the stack reference.</param>
/// <param name="args">The arguments to use to populate this resource's properties.</param>
/// <param name="options">A bag of options that control this resource's behavior.</param>
public StackReference(string name, StackReferenceArgs? args = null, ResourceOptions? options = null)
public StackReference(string name, StackReferenceArgs? args = null, CustomResourceOptions? options = null)
: base("pulumi:pulumi:StackReference",
name,
new StackReferenceArgs { Name = args?.Name ?? name },