farmer icon indicating copy to clipboard operation
farmer copied to clipboard

Event Hub as dependency is invalid

Open BrianVallelunga opened this issue 2 years ago • 4 comments

I'm having issues in setting an Event Hub instance as a dependency of a web app. The issue seems to be the way the Event Hub is referenced. Here's the code:

let myEventHub =
    eventHub {
        namespace_name "my-event-hubs-ns"
        sku EventHub.Standard
        name "my-event-hub"
    }

Then I reference it in a web app:

let myWebApp = webApp {
    name "my-web-app"
    depends_on myEventHub 
    setting "EventHubs" myEventHub.DefaultKey
}

The resulting ARM template has the following:

"dependsOn": [
    "[resourceId('Microsoft.EventHub/namespaces', 'my-event-hubs-ns')]",
    "[resourceId('Microsoft.EventHub/namespaces/eventhubs', 'my-event-hub')]"
]

This results in the following error:

Unable to evaluate template language function 'resourceId': the type 'Microsoft.EventHub/namespaces/eventhubs' requires '2' resource name argument(s).

From what I can tell, the issue is in the second reference to the Event Hub itself, not the namespace. Changing it to include the Event Hub namespace seems to solve the issue:

"dependsOn": [
    "[resourceId('Microsoft.EventHub/namespaces', 'my-event-hubs-ns')]",
    "[resourceId('Microsoft.EventHub/namespaces/eventhubs', 'my-event-hubs-ns', 'my-event-hub')]"
]

I'm happy to take a stab at trying to fix this, but am not quite sure where to look in the code.

BrianVallelunga avatar Dec 13 '23 15:12 BrianVallelunga

I've been attempting to fix this issue, but am coming up short. The tricky thing about the EventHub builder is that unlike the ServiceBus builder, the Hub and the Namespace are combined. What I think needs to happen is for the EventHub record to add a Namespace: LinkedResource field that points back to the EventHubNamespace, much like the Queue record for the ServiceBus. This can then be used to generate the correct dependency.

That said, I've been unsuccessful in getting the generation fixed so that the three-part version is output as a dependency. I thought replacing the Create method name with both the namespace name and hub name would work, but I've had no success. This produces the exact same resourceId reference.

// In type EventHub
interface IArmResource with
    member this.ResourceId = eventHubs.resourceId (this.Namespace.Name / this.Name)

    member this.JsonModel =
        {| eventHubs.Create(this.Namespace.Name / this.Name, this.Location, this.Dependencies, this.Tags) with
            properties =

BrianVallelunga avatar Dec 15 '23 13:12 BrianVallelunga

Let me take a look at this one.

isaacabraham avatar Jan 05 '24 14:01 isaacabraham

@isaacabraham Thanks for checking this out.

In an effort to support this properly, I first added a Namespace field to the EventHub type in the Namespaces module.

    type EventHub =
        {
            Name: ResourceName
            Namespace: LinkedResource
            Location: Location
            MessageRetentionDays: int option
            Partitions: int
            Dependencies: ResourceId Set
            CaptureDestination: CaptureDestination option
            Tags: Map<string, string>
        }

Then, in the BuildResources method, I assign it the value:

Namespace = Managed(namespaces.resourceId this.EventHubNamespaceName)

I think this is the correct approach and is modeled after the Service Bus. I believe the problem is in the ARM generation.

BrianVallelunga avatar Jan 05 '24 15:01 BrianVallelunga

Thank you. I'll test it out.

BrianVallelunga avatar Jul 03 '24 02:07 BrianVallelunga