Move .NET serialization attributes to Pulumi namespace (#3902)
Move .NET serialization attributes to Pulumi namespace, deprecate the ones in Pulumi.Serialization
This commit is contained in:
parent
d68d22a541
commit
f1cdce9488
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -8,7 +8,7 @@
|
|||
coverage.cov
|
||||
*.coverprofile
|
||||
|
||||
/.idea/
|
||||
**/.idea/
|
||||
*.iml
|
||||
|
||||
# VSCode creates this binary when running tests in the debugger
|
||||
|
|
|
@ -14,6 +14,9 @@ CHANGELOG
|
|||
- Expose resource options, parent, dependencies, and provider config to policies.
|
||||
[#3862](https://github.com/pulumi/pulumi/pull/3862)
|
||||
|
||||
- Move .NET SDK attributes to the root namespace.
|
||||
[#3902](https://github.com/pulumi/pulumi/pull/3902)
|
||||
|
||||
## 1.10.1 (2020-02-06)
|
||||
- Support stack references in the Go SDK.
|
||||
[#3829](https://github.com/pulumi/pulumi/pull/3829)
|
||||
|
|
|
@ -84,6 +84,8 @@ Pulumi.IDeployment.StackName.get -> string
|
|||
Pulumi.Input<T>
|
||||
Pulumi.InputArgs
|
||||
Pulumi.InputArgs.InputArgs() -> void
|
||||
Pulumi.InputAttribute
|
||||
Pulumi.InputAttribute.InputAttribute(string name, bool required = false, bool json = false) -> void
|
||||
Pulumi.InputExtensions
|
||||
Pulumi.InputJson
|
||||
Pulumi.InputJson.InputJson() -> void
|
||||
|
@ -116,6 +118,13 @@ Pulumi.Output<T>.Apply<U>(System.Func<T, Pulumi.Input<U>> func) -> Pulumi.Output
|
|||
Pulumi.Output<T>.Apply<U>(System.Func<T, Pulumi.Output<U>> func) -> Pulumi.Output<U>
|
||||
Pulumi.Output<T>.Apply<U>(System.Func<T, System.Threading.Tasks.Task<U>> func) -> Pulumi.Output<U>
|
||||
Pulumi.Output<T>.Apply<U>(System.Func<T, U> func) -> Pulumi.Output<U>
|
||||
Pulumi.OutputAttribute
|
||||
Pulumi.OutputAttribute.Name.get -> string
|
||||
Pulumi.OutputAttribute.OutputAttribute(string name = null) -> void
|
||||
Pulumi.OutputConstructorAttribute
|
||||
Pulumi.OutputConstructorAttribute.OutputConstructorAttribute() -> void
|
||||
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
|
||||
|
|
|
@ -23,14 +23,22 @@ namespace Pulumi
|
|||
{
|
||||
var fieldQuery =
|
||||
from field in this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
|
||||
let attr = field.GetCustomAttribute<InputAttribute>()
|
||||
where attr != null
|
||||
let attr1 = field.GetCustomAttribute<Pulumi.InputAttribute>()
|
||||
#pragma warning disable 618
|
||||
let attr2 = field.GetCustomAttribute<Pulumi.Serialization.InputAttribute>()
|
||||
#pragma warning restore 618
|
||||
where attr1 != null || attr2 != null
|
||||
let attr = attr1 ?? new Pulumi.InputAttribute(attr2.Name, attr2.IsRequired, attr2.Json)
|
||||
select (attr, memberName: field.Name, memberType: field.FieldType, getValue: (Func<object, object?>)field.GetValue);
|
||||
|
||||
var propQuery =
|
||||
from prop in this.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
|
||||
let attr = prop.GetCustomAttribute<InputAttribute>()
|
||||
where attr != null
|
||||
let attr1 = prop.GetCustomAttribute<Pulumi.InputAttribute>()
|
||||
#pragma warning disable 618
|
||||
let attr2 = prop.GetCustomAttribute<Pulumi.Serialization.InputAttribute>()
|
||||
#pragma warning restore 618
|
||||
where attr1 != null || attr2 != null
|
||||
let attr = attr1 ?? new Pulumi.InputAttribute(attr2.Name, attr2.IsRequired, attr2.Json)
|
||||
select (attr, memberName: prop.Name, memberType: prop.PropertyType, getValue: (Func<object, object?>)prop.GetValue);
|
||||
|
||||
var all = fieldQuery.Concat(propQuery).ToList();
|
||||
|
|
81
sdk/dotnet/Pulumi/Serialization/Attributes.Legacy.cs
Normal file
81
sdk/dotnet/Pulumi/Serialization/Attributes.Legacy.cs
Normal file
|
@ -0,0 +1,81 @@
|
|||
// Copyright 2016-2019, Pulumi Corporation
|
||||
|
||||
using System;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
namespace Pulumi.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute used by a Pulumi Cloud Provider Package to mark Resource output properties.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
[Obsolete("Use Pulumi.OutputAttribute instead")]
|
||||
public sealed class OutputAttribute : Attribute
|
||||
{
|
||||
public string? Name { get; }
|
||||
|
||||
public OutputAttribute(string? name = null)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute used by a Pulumi Cloud Provider Package to mark Resource input fields and
|
||||
/// properties.
|
||||
/// <para/>
|
||||
/// Note: for simple inputs (i.e. <see cref="Input{T}"/> this should just be placed on the
|
||||
/// property itself. i.e. <c>[Input] Input<string> Acl</c>.
|
||||
///
|
||||
/// For collection inputs (i.e. <see cref="InputList{T}"/> this should be placed on the
|
||||
/// backing field for the property. i.e.
|
||||
///
|
||||
/// <code>
|
||||
/// [Input] private InputList<string> _acls;
|
||||
/// public InputList<string> Acls
|
||||
/// {
|
||||
/// get => _acls ?? (_acls = new InputList<string>());
|
||||
/// set => _acls = value;
|
||||
/// }
|
||||
/// </code>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||
[Obsolete("Use Pulumi.InputAttribute instead")]
|
||||
public sealed class InputAttribute : Attribute
|
||||
{
|
||||
internal string Name { get; }
|
||||
internal bool IsRequired { get; }
|
||||
internal bool Json { get; }
|
||||
|
||||
public InputAttribute(string name, bool required = false, bool json = false)
|
||||
{
|
||||
Name = name;
|
||||
IsRequired = required;
|
||||
Json = json;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute used by a Pulumi Cloud Provider Package to mark complex types used for a Resource
|
||||
/// output property. A complex type must have a single constructor in it marked with the
|
||||
/// <see cref="OutputConstructorAttribute"/> attribute.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
[Obsolete("Use Pulumi.OutputTypeAttribute instead")]
|
||||
public sealed class OutputTypeAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute used by a Pulumi Cloud Provider Package to marks the constructor for a complex
|
||||
/// property type so that it can be instantiated by the Pulumi runtime.
|
||||
///
|
||||
/// The constructor should contain parameters that map to the resultant <see
|
||||
/// cref="Struct.Fields"/> returned by the engine.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Constructor)]
|
||||
[Obsolete("Use Pulumi.OutputConstructorAttribute instead")]
|
||||
public sealed class OutputConstructorAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
|
@ -3,10 +3,12 @@
|
|||
using System;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
namespace Pulumi.Serialization
|
||||
namespace Pulumi
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute used by a Pulumi Cloud Provider Package to mark Resource output properties.
|
||||
/// Attribute used by a mark <see cref="Resource"/> output properties. Use this attribute
|
||||
/// in your Pulumi programs to mark outputs of <see cref="ComponentResource"/> and
|
||||
/// <see cref="Stack"/> resources.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class OutputAttribute : Attribute
|
||||
|
@ -20,8 +22,8 @@ namespace Pulumi.Serialization
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute used by a Pulumi Cloud Provider Package to mark Resource input fields and
|
||||
/// properties.
|
||||
/// Attribute used by a Pulumi Cloud Provider Package to mark <see cref="Resource"/> input
|
||||
/// fields and properties.
|
||||
/// <para/>
|
||||
/// Note: for simple inputs (i.e. <see cref="Input{T}"/> this should just be placed on the
|
||||
/// property itself. i.e. <c>[Input] Input<string> Acl</c>.
|
||||
|
|
|
@ -113,14 +113,17 @@ namespace Pulumi.Serialization
|
|||
$"Unexpected generic target type {targetType.FullName} when deserializing {context}");
|
||||
}
|
||||
|
||||
if (targetType.GetCustomAttribute<OutputTypeAttribute>() == null)
|
||||
if (targetType.GetCustomAttribute<Pulumi.OutputTypeAttribute>() == null
|
||||
#pragma warning disable 618
|
||||
&& targetType.GetCustomAttribute<Pulumi.Serialization.OutputTypeAttribute>() == null)
|
||||
#pragma warning restore 618
|
||||
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(OutputConstructorAttribute)}] constructor when deserializing {context}"));
|
||||
$"Expected target type {targetType.FullName} to have [{nameof(Pulumi.OutputConstructorAttribute)}] constructor when deserializing {context}"));
|
||||
|
||||
var (dictionary, tempException) = TryEnsureType<ImmutableDictionary<string, object>>(context, val);
|
||||
if (tempException != null)
|
||||
|
@ -365,21 +368,24 @@ $@"{context} contains invalid type {targetType.FullName}:
|
|||
}
|
||||
}
|
||||
|
||||
var propertyTypeAttribute = targetType.GetCustomAttribute<OutputTypeAttribute>();
|
||||
var propertyTypeAttribute = (Attribute?)targetType.GetCustomAttribute<Pulumi.OutputTypeAttribute>()
|
||||
#pragma warning disable 618
|
||||
?? targetType.GetCustomAttribute<Pulumi.Serialization.OutputTypeAttribute>();
|
||||
#pragma warning restore 618
|
||||
if (propertyTypeAttribute == null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$@"{context} contains invalid type {targetType.FullName}. Allowed types are:
|
||||
String, Boolean, Int32, Double,
|
||||
Nullable<...>, ImmutableArray<...> and ImmutableDictionary<string, ...> or
|
||||
a class explicitly marked with the [{nameof(OutputTypeAttribute)}].");
|
||||
a class explicitly marked with the [{nameof(Pulumi.OutputTypeAttribute)}].");
|
||||
}
|
||||
|
||||
var constructor = GetPropertyConstructor(targetType);
|
||||
if (constructor == null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$@"{targetType.FullName} had [{nameof(OutputTypeAttribute)}], but did not contain constructor marked with [{nameof(OutputConstructorAttribute)}].");
|
||||
$@"{targetType.FullName} had [{nameof(Pulumi.OutputTypeAttribute)}], but did not contain constructor marked with [{nameof(Pulumi.OutputConstructorAttribute)}].");
|
||||
}
|
||||
|
||||
foreach (var param in constructor.GetParameters())
|
||||
|
@ -390,6 +396,9 @@ $@"{targetType.FullName} had [{nameof(OutputTypeAttribute)}], but did not contai
|
|||
|
||||
private static ConstructorInfo GetPropertyConstructor(System.Type outputTypeArg)
|
||||
=> outputTypeArg.GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(
|
||||
c => c.GetCustomAttributes<OutputConstructorAttribute>() != null);
|
||||
c => c.GetCustomAttributes<Pulumi.OutputConstructorAttribute>() != null
|
||||
#pragma warning disable 618
|
||||
|| c.GetCustomAttributes<Pulumi.Serialization.OutputConstructorAttribute>() != null);
|
||||
#pragma warning restore 618
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,12 +63,15 @@ namespace Pulumi.Serialization
|
|||
var type = resource.GetResourceType();
|
||||
|
||||
var query = from property in resource.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
|
||||
let attr = property.GetCustomAttribute<OutputAttribute>()
|
||||
where attr != null
|
||||
select (property, attr);
|
||||
let attr1 = property.GetCustomAttribute<Pulumi.OutputAttribute>()
|
||||
#pragma warning disable 618
|
||||
let attr2 = property.GetCustomAttribute<Pulumi.Serialization.OutputAttribute>()
|
||||
#pragma warning restore 618
|
||||
where attr1 != null || attr2 != null
|
||||
select (property, attrName: attr1?.Name ?? attr2?.Name);
|
||||
|
||||
var result = ImmutableDictionary.CreateBuilder<string, IOutputCompletionSource>();
|
||||
foreach (var (prop, attr) in query.ToList())
|
||||
foreach (var (prop, attrName) in query.ToList())
|
||||
{
|
||||
var propType = prop.PropertyType;
|
||||
var propFullName = $"[Output] {resource.GetType().FullName}.{prop.Name}";
|
||||
|
@ -93,7 +96,7 @@ namespace Pulumi.Serialization
|
|||
|
||||
setMethod.Invoke(resource, new[] { completionSource.Output });
|
||||
|
||||
var outputName = attr.Name ?? prop.Name;
|
||||
var outputName = attrName ?? prop.Name;
|
||||
result.Add(outputName, completionSource);
|
||||
}
|
||||
|
||||
|
|
|
@ -79,9 +79,12 @@ namespace Pulumi
|
|||
internal void RegisterPropertyOutputs()
|
||||
{
|
||||
var outputs = (from property in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
|
||||
let attr = property.GetCustomAttribute<OutputAttribute>()
|
||||
where attr != null
|
||||
let name = attr.Name ?? property.Name
|
||||
let attr1 = property.GetCustomAttribute<Pulumi.OutputAttribute>()
|
||||
#pragma warning disable 618
|
||||
let attr2 = property.GetCustomAttribute<Pulumi.Serialization.OutputAttribute>()
|
||||
#pragma warning restore 618
|
||||
where attr1 != null || attr2 != null
|
||||
let name = attr1?.Name ?? attr2?.Name ?? property.Name
|
||||
select new KeyValuePair<string, object?>(name, property.GetValue(this))).ToList();
|
||||
|
||||
// Check that none of the values are null: catch unassigned outputs
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Pulumi;
|
||||
using Pulumi.Serialization;
|
||||
|
||||
class MyStack : Stack
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue