Hello Quick form of question - DependsOn doesn't a...
# dotnet
s
Hello Quick form of question - DependsOn doesn't appear to honor dynamically generated list of Pulumi.Resource objects properly. Long form - I'm using Azure, C# and Pulumi.AzureNative. I'm create an AppServicePlan, then create many WebApps in it based off an array of names (the only difference). I then create a Dictionary of the names to resource names for use in deployment automation. This is saved as a config value (also a github value but doesn't matter for this question) And putting this question here because it appears a DependsOn limitation, not an Azure limitation. The problem - the config values comes out empty {} because it doesn't honor a dynamically created array of Depends objects. So on first run the
application_map
== {} On a subsequent run it's
application_map
== { "name0":"dev-webapp-name0-90fh3g","name1":"dev-webapp-name1-516woe", ... } This is despite the
Console.WriteLine($"newdict: {JsonSerializer.Serialize(newdict)}");
command always outputting the "correct" value. Any ideas? options to overcome this other than manually create N WebApps instead of deriving from an array? Thanks Example below Pulumi.yaml
Copy code
config:
  KEY:names:
    - name0
    - name1
    - name2
    - name3
...
Copy code
var config = new Pulumi.Config("KEY");
 var names = config.RequireObject<List<string>>("names");

    var appServicePlan = new AppServicePlan(appServicePlanName, new()
    {
      // Name = appServicePlanName,
      Kind = "app",
      Location = location,
      ResourceGroupName = resourceGroup.Name,
      ...,
    });

    var apps = names .ToDictionary(name => name, name => new LinuxDockerWebAppComponent(name,
      new LinuxDockerWebAppArgs
      {
        ResourceGroup = resourceGroup.Name,
        AppServicePlanId = appServicePlan .LinuxAppServicePlanId,
        SubscriptionId = SubscriptionId,
        AppConfig = appConfigConnectionString,
        RegistryRg = registry_rg,
        RegistryName = registry,
      })
    );

    var newdict = new Dictionary<string, string>();
    apps.ToList().ForEach(kv => kv.Value.ResourceName.Apply(v => newdict[kv.Key] = v));
    var apps_json = JsonSerializer.Serialize(newdict);
    Console.WriteLine($"newdict: {JsonSerializer.Serialize(newdict)}");

    List<Pulumi.Resource> dependItems = new List<Pulumi.Resource>();
    dependItems.AddRange(apps.Values.ToList());

    var appMap= new KeyValue("application_map", new KeyValueArgs
    {
      KeyValueName = "application_map",
      ResourceGroupName = resourceGroup.Name,
      ConfigStoreName = appConfig.Name,
      Value = apps_json,
      ContentType = "application/json"
    }, new CustomResourceOptions
    {
      DependsOn = dependItems,
    });
e
So
Apply(v => newdict[kv.Key] = v)
is a little suspect because Apply's run inside Tasks asynchronously so that dictionary assignment might not happen when you expect it to. I don't think this is a dependsOn issue, just async mutation issues.
s
Thanks Fraser I don't disagree it's very likely the async mutation instead. But why is this line
Console.WriteLine($"newdict: {JsonSerializer.Serialize(newdict)}");
coming out correct? Do you have better suggestions on how to arrive at my goal? I've been trying many things but nothing seems to 100% guarantee all WebApp objects have finalized their state to use in name mapping And DependsOn association. I'm also doing testing with
--parallel 1
for this and other annoyances of too many api calls, which may have to be a temporary workaround. Edit: it's just name use for that line. Ignore - that is calculated before the resource is even attempted created. Other part of the question still stands though.
e
So don't use "Apply" when building the dictionary, just make a dictionary of
<string, Output<string>>
then use
Output.JsonSerialize
instead of the normal json serialise so it handles the outputs in it.
s
Excellent thanks! I never found the Output.JsonSerialize in my digging. Also - worked like a charm