This commit is contained in:
Fraser Waters 2021-11-11 16:22:59 +00:00
parent e20ffbebba
commit 08414a7b99
8 changed files with 129 additions and 24 deletions

View file

@ -55,6 +55,7 @@ test_all:: dotnet_test auto_test
dist::
go install -ldflags "-X github.com/pulumi/pulumi/sdk/v3/go/common/version.Version=${DOTNET_VERSION}" ${LANGHOST_PKG}
cp ./dist/pulumi-resource-pulumi-dotnet "$$(go env GOPATH)"/bin/
brew:: BREW_VERSION := $(shell ../../scripts/get-version HEAD)
brew::

View file

@ -36,10 +36,10 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="2.9.6">
<!--<PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="2.9.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</PackageReference>-->
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.16" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="OneOf" Version="2.1.151" />

View file

@ -1,5 +1,6 @@
// Copyright 2016-2019, Pulumi Corporation
using System;
using Pulumi.Serialization;
namespace Pulumi
@ -62,5 +63,10 @@ namespace Pulumi
remote: false, dependency: dependency)
{
}
private protected CustomResource( Func<Resource, string> typeProvider, string name, ResourceArgs? args, CustomResourceOptions? options = null)
: base(typeProvider, name, custom: true, args ?? ResourceArgs.Empty, options ?? new CustomResourceOptions(), remote: false)
{
}
}
}

View file

@ -0,0 +1,38 @@
// Copyright 2016-2019, Pulumi Corporation
using System;
namespace Pulumi
{
public class DynamicResource : CustomResource
{
private static string GetTypeName(Resource resource)
{
var type = resource.GetType();
var typeName = $"dynamic/{type.Namespace}:{type.Name}";
return $"pulumi-dotnet:{typeName}";
}
private static ResourceArgs SerializeProvider(DynamicResourceProvider provider, ResourceArgs? args)
{
return args!;
//
// if PROVIDER_KEY in props:
// raise Exception("A dynamic resource must not define the __provider key")
//
// props = cast(dict, props)
// props[PROVIDER_KEY] = serialize_provider(provider)
//
// super().__init__(f"pulumi-python:{self._resource_type_name}", name, props, opts)
//
}
#pragma warning disable RS0022 // Constructor make noninheritable base class inheritable
public DynamicResource(DynamicResourceProvider provider, string name, ResourceArgs? args, CustomResourceOptions? options = null)
: base((Func<Resource, string>)GetTypeName, name, SerializeProvider(provider, args), options)
#pragma warning restore RS0022 // Constructor make noninheritable base class inheritable
{
}
}
}

View file

@ -0,0 +1,15 @@
// Copyright 2016-2019, Pulumi Corporation
using System;
using System.Collections.Generic;
namespace Pulumi
{
public abstract class DynamicResourceProvider
{
public virtual (string, IDictionary<string, object?>) Create(IDictionary<string, object?> properties)
{
throw new NotImplementedException();
}
}
}

View file

@ -20,33 +20,33 @@ namespace Pulumi
/// 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
/// depending on all the CustomResource children of that component.
///
///
/// Important! We only walk through ComponentResources.They're the only resources that
/// serve as an aggregation of other primitive(i.e.custom) resources.While a custom resource
/// can be a parent of other resources, we don't want to ever depend on those child
/// resource. If we do, it's simple to end up in a situation where we end up depending on a
/// child resource that has a data cycle dependency due to the data passed into it. An
/// example of how this would be bad is:
///
///
/// <c>
/// var c1 = new CustomResource("c1");
/// var c2 = new CustomResource("c2", { parentId = c1.id }, { parent = c1 });
/// var c3 = new CustomResource("c3", { parentId = c1.id }, { parent = c1 });
/// </c>
///
///
/// The problem here is that 'c2' has a data dependency on 'c1'. If it tries to wait on
/// 'c1' it will walk to the children and wait on them.This will mean it will wait on 'c3'.
/// But 'c3' will be waiting in the same manner on 'c2', and a cycle forms. This normally
/// does not happen with ComponentResources as they do not have any data flowing into
/// them.The only way you would be able to have a problem is if you had this sort of coding
/// pattern:
///
///
/// <c>
/// var c1 = new ComponentResource("c1");
/// var c2 = new CustomResource("c2", { parentId = c1.urn }, { parent: c1 });
/// var c3 = new CustomResource("c3", { parentId = c1.urn }, { parent: c1 });
/// </c>
///
///
/// However, this would be pretty nonsensical as there is zero need for a custom resource to
/// ever need to reference the urn of a component resource. So it's acceptable if that sort
/// of pattern failed in practice.
@ -120,8 +120,32 @@ namespace Pulumi
private protected Resource(
string type, string name, bool custom,
ResourceArgs args, ResourceOptions options,
bool remote = false, bool dependency = false) :
this(_ => type, name, custom, args, options, remote, dependency)
{
}
/// <summary>
/// Creates and registers a new resource object. <paramref name="typeProvider"/> is the fully
/// qualified type token and <paramref name="name"/> is the "name" part to use in creating a
/// stable and globally unique URN for the object. dependsOn is an optional list of other
/// resources that this resource depends on, controlling the order in which we perform
/// resource operations.
/// </summary>
/// <param name="typeProvider">The type of the resource.</param>
/// <param name="name">The unique name of the resource.</param>
/// <param name="custom">True to indicate that this is a custom resource, managed by a plugin.</param>
/// <param name="args">The arguments to use to populate the new resource.</param>
/// <param name="options">A bag of options that control this resource's behavior.</param>
/// <param name="remote">True if this is a remote component resource.</param>
/// <param name="dependency">True if this is a synthetic resource used internally for dependency tracking.</param>
private protected Resource(
Func<Resource, string> typeProvider, string name, bool custom,
ResourceArgs args, ResourceOptions options,
bool remote = false, bool dependency = false)
{
var type = typeProvider(this);
if (dependency)
{
_type = "";

View file

@ -0,0 +1,3 @@
#!/bin/sh
echo $(pwd)

View file

@ -1,32 +1,50 @@
// Copyright 2016-2019, Pulumi Corporation. All rights reserved.
// Copyright 2016-2021, Pulumi Corporation. All rights reserved.
using System.Collections.Generic;
using System.Threading.Tasks;
using Pulumi;
//import binascii
//import os
//from pulumi import ComponentResource, export
//from pulumi.dynamic import Resource, ResourceProvider, CreateResult//
public sealed class RandomResourceProvider : DynamicResourceProvider
{
public override (string, IDictionary<string, object>) Create(IDictionary<string, object> properties)
{
var random = new System.Random();
var buffer = new byte[15];
random.NextBytes(buffer);
var val = System.Convert.ToBase64String(buffer);
//class RandomResourceProvider(ResourceProvider):
// def create(self, props):
// val = binascii.b2a_hex(os.urandom(15)).decode("ascii")
// return CreateResult(val, { "val": val })//
return (val, new Dictionary<string, object>{ { "val", val } });
}
}
//class Random(Resource):
// val: str
// def __init__(self, name, opts = None):
// super().__init__(RandomResourceProvider(), name, {"val": ""}, opts)//
public sealed class RandomArgs : ResourceArgs
{
[Input("val")]
public Input<string> Val { get; set; }
}
//r = Random("foo")//
class Random : DynamicResource
{
[Output("val")]
public Output<string> Val { get; private set; }
//export("random_id", r.id)
//export("random_val", r.val)
public Random(string name, CustomResourceOptions options = null)
: base(new RandomResourceProvider(), name, new RandomArgs() { Val = "" }, options)
{
}
}
class Program
{
static Task<int> Main(string[] args)
{
return Deployment.RunAsync(() => {});
return Deployment.RunAsync(() => {
var r = new Random("foo");
return new Dictionary<string, object> {
{ "random_id", r.Id },
{ "random_val", r.Val }
};
});
}
}