Skip to content

Commit

Permalink
Tests for .NET aliases (#3420)
Browse files Browse the repository at this point in the history
Tests for .NET aliases
  • Loading branch information
mikhailshilkov committed Nov 20, 2019
1 parent 35b32f2 commit 6f55e1a
Show file tree
Hide file tree
Showing 27 changed files with 556 additions and 369 deletions.
12 changes: 6 additions & 6 deletions sdk/dotnet/Pulumi/Core/Urn.cs
@@ -1,4 +1,4 @@
// Copyright 2016-2018, Pulumi Corporation
// Copyright 2016-2019, Pulumi Corporation

using System;

Expand All @@ -8,17 +8,17 @@ namespace Pulumi
/// An automatically generated logical URN, used to stably identify resources. These are created
/// automatically by Pulumi to identify resources. They cannot be manually constructed.
/// </summary>
internal static class Urn
public static class Urn
{
/// <summary>
/// Computes a URN from the combination of a resource name, resource type, optional parent,
/// optional project and optional stack.
/// </summary>
/// <returns></returns>
internal static Output<string> Create(
public static Output<string> Create(
Input<string> name, Input<string> type,
Resource? parent, Input<string>? parentUrn,
Input<string>? project, Input<string>? stack)
Resource? parent = null, Input<string>? parentUrn = null,
Input<string>? project = null, Input<string>? stack = null)
{
if (parent != null && parentUrn != null)
throw new ArgumentException("Only one of 'parent' and 'parentUrn' can be non-null.");
Expand All @@ -36,7 +36,7 @@ internal static class Urn
}
else
{
parentPrefix = Output.Create($"urn:pulumi:{stack ?? Deployment.Instance.StackName}::{project ?? Deployment.Instance.ProjectName}::");
parentPrefix = Output.Format($"urn:pulumi:{stack ?? Deployment.Instance.StackName}::{project ?? Deployment.Instance.ProjectName}::");
}

return Output.Format($"{parentPrefix}{type}::{name}");
Expand Down
3 changes: 2 additions & 1 deletion sdk/dotnet/Pulumi/Deployment/Deployment_Prepare.cs
@@ -1,5 +1,6 @@
// Copyright 2016-2019, Pulumi Corporation

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
Expand Down Expand Up @@ -75,7 +76,7 @@ public partial class Deployment
foreach (var alias in res._aliases)
{
var aliasVal = await alias.ToOutput().GetValueAsync().ConfigureAwait(false);
if (!uniqueAliases.Add(aliasVal))
if (uniqueAliases.Add(aliasVal))
{
aliases.Add(aliasVal);
}
Expand Down
2 changes: 2 additions & 0 deletions sdk/dotnet/Pulumi/PublicAPI.Unshipped.txt
Expand Up @@ -164,6 +164,7 @@ Pulumi.Serialization.OutputTypeAttribute
Pulumi.Serialization.OutputTypeAttribute.OutputTypeAttribute() -> void
Pulumi.StringAsset
Pulumi.StringAsset.StringAsset(string text) -> void
Pulumi.Urn
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.Deployment.Instance.get -> Pulumi.IDeployment
Expand Down Expand Up @@ -230,4 +231,5 @@ static Pulumi.OutputExtensions.First<T>(this Pulumi.Output<System.Collections.Im
static Pulumi.OutputExtensions.GetAt<T>(this Pulumi.Output<System.Collections.Immutable.ImmutableArray<T>> array, Pulumi.Input<int> index) -> Pulumi.Output<T>
static Pulumi.OutputExtensions.Length<T>(this Pulumi.Output<System.Collections.Immutable.ImmutableArray<T>> array) -> Pulumi.Output<int>
static Pulumi.ResourceOptions.Merge(Pulumi.ResourceOptions options1, Pulumi.ResourceOptions options2) -> Pulumi.ResourceOptions
static Pulumi.Urn.Create(Pulumi.Input<string> name, Pulumi.Input<string> type, Pulumi.Resource parent = null, Pulumi.Input<string> parentUrn = null, Pulumi.Input<string> project = null, Pulumi.Input<string> stack = null) -> Pulumi.Output<string>
static readonly Pulumi.ResourceArgs.Empty -> Pulumi.ResourceArgs
20 changes: 20 additions & 0 deletions tests/integration/aliases/aliases_test.go
Expand Up @@ -61,3 +61,23 @@ func TestPythonAliases(t *testing.T) {
})
}
}

func TestDotNetAliases(t *testing.T) {
for _, dir := range dirs {
d := path.Join("dotnet", dir)
t.Run(d, func(t *testing.T) {
integration.ProgramTest(t, &integration.ProgramTestOptions{
Dir: path.Join(d, "step1"),
Dependencies: []string{"Pulumi"},
Quick: true,
EditDirs: []integration.EditDir{
{
Dir: path.Join(d, "step2"),
Additive: true,
ExpectNoChanges: true,
},
},
})
})
}
}
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>

</Project>
@@ -0,0 +1,72 @@
// Copyright 2016-2019, Pulumi Corporation. All rights reserved.

using System.Threading.Tasks;
using Pulumi;

class Resource : ComponentResource
{
public Resource(string name, ComponentResourceOptions options = null)
: base("my:module:Resource", name, options)
{
}
}

// Scenario #2 - adopt a resource into a component
class Component : ComponentResource
{
public Component(string name, ComponentResourceOptions options = null)
: base("my:module:Component", name, options)
{
}
}

// Scenario 3: adopt this resource into a new parent.
class Component2 : ComponentResource
{
public Component2(string name, ComponentResourceOptions options = null)
: base("my:module:Component2", name, options)
{
}
}

// Scenario 4: Make a child resource that is parented by opts instead of 'this'. Fix
// in the next step to be parented by this. Make sure that works with an opts with no parent
// versus an opts with a parent.

class Component3 : ComponentResource
{
public Component3(string name, ComponentResourceOptions options = null)
: base("my:module:Component3", name, options)
{
new Component2(name + "-child", options);
}
}

// Scenario 5: Allow multiple aliases to the same resource.
class Component4 : ComponentResource
{
public Component4(string name, ComponentResourceOptions options = null)
: base("my:module:Component4", name, options)
{
}
}


class Program
{
static Task<int> Main(string[] args)
{
return Deployment.RunAsync(() =>
{
var res2 = new Resource("res2");
var comp2 = new Component("comp2");
new Component2("unparented");
new Component3("parentedbystack");
new Component3("parentedbycomponent", new ComponentResourceOptions { Parent = comp2 });
new Component4("duplicateAliases", new ComponentResourceOptions { Parent = comp2 });
});
}
}
@@ -0,0 +1,3 @@
name: aliases_adopt_into_component
description: A program that replaces a resource with a new name and alias.
runtime: dotnet
109 changes: 109 additions & 0 deletions tests/integration/aliases/dotnet/adopt_into_component/step2/Program.cs
@@ -0,0 +1,109 @@
// Copyright 2016-2019, Pulumi Corporation. All rights reserved.

using System;
using System.Threading.Tasks;
using Pulumi;

class Resource : ComponentResource
{
public Resource(string name, ComponentResourceOptions options = null)
: base("my:module:Resource", name, options)
{
}
}

// Scenario #2 - adopt a resource into a component. The component author is the same as the component user, and changes
// the component to be able to adopt the resource that was previously defined separately...
class Component : ComponentResource
{
private Resource resource;

public Component(string name, ComponentResourceOptions options = null)
: base("my:module:Component", name, options)
{
// The resource creation was moved from top level to inside the component.
this.resource = new Resource($"{name}-child",
new ComponentResourceOptions
{
// With a new parent
Parent = this,
// But with an alias provided based on knowing where the resource existing before - in this case at top
// level. We use an absolute URN instead of a relative `Alias` because we are referencing a fixed resource
// that was in some arbitrary other location in the hierarchy prior to being adopted into this component.
Aliases = { Pulumi.Urn.Create("res2", "my:module:Resource").Apply(urn => new Alias { Urn = urn }) },
});
}
}

// Scenario 3: adopt this resource into a new parent.
class Component2 : ComponentResource
{
public Component2(string name, ComponentResourceOptions options = null)
: base("my:module:Component2", name, options)
{
}
}


// Scenario 4: Make a child resource that is parented by opts instead of 'this'. Fix
// in the next step to be parented by this. Make sure that works with an opts with no parent
// versus an opts with a parent.

class Component3 : ComponentResource
{
public Component3(string name, ComponentResourceOptions options = null)
: base("my:module:Component3", name, options)
{
new Component2(name + "-child",
new ComponentResourceOptions
{
Aliases = { new Alias { Parent = options?.Parent, NoParent = options?.Parent == null } },
Parent = this
});
}
}

// Scenario 5: Allow multiple aliases to the same resource.
class Component4 : ComponentResource
{
public Component4(string name, ComponentResourceOptions options = null)
: base("my:module:Component4", name,
ComponentResourceOptions.Merge(
new ComponentResourceOptions
{
Aliases =
{
new Alias { NoParent = true },
new Alias { NoParent = true }
},
},
options))
{
}
}

class Program
{
static Task<int> Main(string[] args)
{
return Deployment.RunAsync(() =>
{
// The creation of the component is unchanged.
var comp2 = new Component("comp2");
// validate that "parent: undefined" means "i didn't have a parent previously"
new Component2("unparented",
new ComponentResourceOptions
{
Aliases = { new Alias { NoParent = true } },
Parent = comp2,
});
new Component3("parentedbystack");
new Component3("parentedbycomponent", new ComponentResourceOptions { Parent = comp2 });
new Component4("duplicateAliases", new ComponentResourceOptions { Parent = comp2 });
});
}
}
8 changes: 8 additions & 0 deletions tests/integration/aliases/dotnet/rename/step1/Aliases.csproj
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>

</Project>
24 changes: 24 additions & 0 deletions tests/integration/aliases/dotnet/rename/step1/Program.cs
@@ -0,0 +1,24 @@
// Copyright 2016-2019, Pulumi Corporation. All rights reserved.

using System.Threading.Tasks;
using Pulumi;

class Resource : ComponentResource
{
public Resource(string name, ComponentResourceOptions options = null)
: base("my:module:Resource", name, options)
{
}
}

class Program
{
static Task<int> Main(string[] args)
{
return Deployment.RunAsync(() =>
{
// Scenario #1 - rename a resource
var res1 = new Resource("res1");
});
}
}
3 changes: 3 additions & 0 deletions tests/integration/aliases/dotnet/rename/step1/Pulumi.yaml
@@ -0,0 +1,3 @@
name: aliases_rename
description: A program that replaces a resource with a new name and alias.
runtime: dotnet
29 changes: 29 additions & 0 deletions tests/integration/aliases/dotnet/rename/step2/Program.cs
@@ -0,0 +1,29 @@
// Copyright 2016-2019, Pulumi Corporation. All rights reserved.

using System.Threading.Tasks;
using Pulumi;

class Resource : ComponentResource
{
public Resource(string name, ComponentResourceOptions options = null)
: base("my:module:Resource", name, options)
{
}
}

class Program
{
static Task<int> Main(string[] args)
{
return Deployment.RunAsync(() =>
{
// Scenario #1 - rename a resource
// This resource was previously named `res1`, we'll alias to the old name.
var res1 = new Resource("newres1",
new ComponentResourceOptions
{
Aliases = { new Alias { Name = "res1" } },
});
});
}
}
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>

</Project>

0 comments on commit 6f55e1a

Please sign in to comment.