Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/little-fans-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@gradientedge/cdk-utils-azure': patch
---

Adding contructs to resolve storage accounts and event grid system topics
32 changes: 32 additions & 0 deletions packages/azure/src/services/eventgrid/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
EventSubscription,
GetSystemTopicResult,
getTopicOutput,
getSystemTopicOutput,
SystemTopic,
SystemTopicEventSubscription,
TlsVersion,
Expand All @@ -19,6 +20,7 @@ import {
EventgridSystemTopicProps,
EventgridTopicProps,
ResolveEventgridTopicProps,
ResolveEventgridSystemTopicProps,
} from './types.js'

/**
Expand Down Expand Up @@ -218,4 +220,34 @@ export class AzureEventgridManager {
{ parent: scope, ...resourceOptions }
)
}

/**
* @summary Method to resolve an existing eventgrid system topic
* @param id scoped id of the resource
* @param scope scope in which this resource is defined
* @param props eventgrid system topic properties
* @param resourceOptions Optional settings to control resource behaviour
* @see [Pulumi Azure Native Event Grid System Topic Lookup]{@link https://www.pulumi.com/registry/packages/azure-native/api-docs/eventgrid/getsystemtopic/}
*/
public resolveEventgridSystemTopic(
id: string,
scope: CommonAzureConstruct,
props: ResolveEventgridSystemTopicProps,
resourceOptions?: ResourceOptions
) {
if (!props) throw new Error(`Props undefined for ${id}`)

return getSystemTopicOutput(
{
systemTopicName:
props.systemTopicName ??
scope.resourceNameFormatter.format(
props.systemTopicName,
scope.props.resourceNameOptions?.eventGridSystemTopic
),
resourceGroupName: props.resourceGroupName ?? scope.resourceNameFormatter.format(scope.props.resourceGroupName),
},
{ parent: scope, ...resourceOptions }
)
}
}
8 changes: 8 additions & 0 deletions packages/azure/src/services/eventgrid/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
EventSubscriptionArgs,
GetSystemTopicOutputArgs,
GetTopicOutputArgs,
SystemTopicArgs,
SystemTopicEventSubscriptionArgs,
Expand Down Expand Up @@ -40,3 +41,10 @@ export interface EventgridSystemTopicEventSubscriptionProps extends SystemTopicE
* @category Interface
*/
export interface ResolveEventgridTopicProps extends GetTopicOutputArgs {}

/**
* Properties for resolving an existing EventGrid system topic
* @see [Pulumi Azure Native Event Grid System Topic]{@link https://www.pulumi.com/registry/packages/azure-native/api-docs/eventgrid/systemtopic/}
* @category Interface
*/
export interface ResolveEventgridSystemTopicProps extends GetSystemTopicOutputArgs {}
55 changes: 55 additions & 0 deletions packages/azure/src/services/storage/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import {
Blob,
BlobContainer,
BlobServiceProperties,
getStorageAccountOutput,
getBlobContainerOutput,
HttpProtocol,
Kind,
listStorageAccountSAS,
Expand All @@ -23,6 +25,8 @@ import { CommonAzureConstruct } from '../../common/index.js'
import {
ContainerSasTokenProps,
ManagementPolicyProps,
ResolveStorageAccountProps,
ResolveStorageContainerProps,
StorageAccountProps,
StorageBlobProps,
StorageContainerProps,
Expand Down Expand Up @@ -269,4 +273,55 @@ export class AzureStorageManager {

return new Table(`${id}`, props, { parent: scope, ...resourceOptions })
}

/**
* @param id scoped id of the resource
* @param scope scope in which this resource is defined
* @param props storage account properties
* @param resourceOptions Optional settings to control resource behaviour
* @see [Pulumi Azure Native Storage Table]{@link https://www.pulumi.com/registry/packages/azure-native/api-docs/storage/table/}
*/
public resolveStorageAccount(
id: string,
scope: CommonAzureConstruct,
props: ResolveStorageAccountProps,
resourceOptions?: ResourceOptions
) {
return getStorageAccountOutput(
{
accountName: scope.resourceNameFormatter.format(
props.accountName?.toString(),
scope.props.resourceNameOptions?.storageAccount
),
resourceGroupName: props.resourceGroupName ?? scope.resourceNameFormatter.format(scope.props.resourceGroupName),
},
{ parent: scope, ...resourceOptions }
)
}

/**
* @param id scoped id of the resource
* @param scope scope in which this resource is defined
* @param props storage account container properties
* @param resourceOptions Optional settings to control resource behaviour

*/
public resolveStorageContainer(
id: string,
scope: CommonAzureConstruct,
props: ResolveStorageContainerProps,
resourceOptions?: ResourceOptions
) {
return getBlobContainerOutput(
{
accountName: scope.resourceNameFormatter.format(
props.accountName?.toString(),
scope.props.resourceNameOptions?.storageAccount
),
containerName: props.containerName,
resourceGroupName: props.resourceGroupName ?? scope.resourceNameFormatter.format(scope.props.resourceGroupName),
},
{ parent: scope, ...resourceOptions }
)
}
}
16 changes: 16 additions & 0 deletions packages/azure/src/services/storage/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import {
BlobArgs,
BlobContainerArgs,
BlobServicePropertiesArgs,
GetStorageAccountOutputArgs,
GetBlobContainerOutputArgs,
ListStorageAccountSASArgs,
ManagementPolicyArgs,
StorageAccountArgs,
Expand Down Expand Up @@ -70,3 +72,17 @@ export interface ContainerSasTokenProps extends ListStorageAccountSASArgs {
/** SAS expiry date in 'YYYY-MM-DD' format; defaults to 7 days from now */
expiry?: string
}

/**
* Properties for resolving an existing Storage account
* @see [Pulumi Azure Native Event Grid Topic]{@link https://www.pulumi.com/registry/packages/azure-native/api-docs/storage/getstorageaccount/}
* @category Interface
*/
export interface ResolveStorageAccountProps extends GetStorageAccountOutputArgs {}

/**
* Properties for resolving an existing Storage account container
* @see [Pulumi Azure Native Event Grid Topic]{@link https://www.pulumi.com/registry/packages/azure-native/api-docs/storage/getstorageaccount/}
* @category Interface
*/
export interface ResolveStorageContainerProps extends GetBlobContainerOutputArgs {}
87 changes: 85 additions & 2 deletions packages/azure/test/services/eventgrid-manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,16 @@ describe('TestAzureEventgridConstruct - Props Undefined', () => {
stack.construct.eventgridManager.resolveEventgridTopic('test-resolve-err', stack.construct, undefined as any)
}).toThrow('Props undefined for test-resolve-err')
})

test('resolveEventgridSystemTopic throws when props are undefined', () => {
expect(() => {
stack.construct.eventgridManager.resolveEventgridSystemTopic(
'test-system-resolve-err',
stack.construct,
undefined as any
)
}).toThrow('Props undefined for test-system-resolve-err')
})
})

/* --- Tests for default value fallback branches --- */
Expand All @@ -287,6 +297,9 @@ class TestMinimalEventgridConstruct extends CommonAzureConstruct {
eventgridTopic: Topic
eventgridSubscription: EventSubscription
eventgridSystemTopic: SystemTopic
eventgridSystemEventSubscription: SystemTopicEventSubscription
resolvedEventgridTopic: pulumi.Output<any>
resolvedEventgridSystemTopic: pulumi.Output<any>

constructor(name: string, props: TestAzureStackProps) {
super(name, props)
Expand All @@ -297,7 +310,6 @@ class TestMinimalEventgridConstruct extends CommonAzureConstruct {
this,
{
topicName: 'test-minimal-eg-topic',
resourceGroupName: 'test-rg-dev',
} as any
)

Expand All @@ -322,11 +334,42 @@ class TestMinimalEventgridConstruct extends CommonAzureConstruct {
this,
{
systemTopicName: 'test-minimal-eg-sys-topic',
resourceGroupName: 'test-rg-dev',
source: '/subscriptions/test-sub/resourceGroups/test-rg-dev/providers/Microsoft.Storage/storageAccounts/testsa',
topicType: 'Microsoft.Storage.StorageAccounts',
} as any
)

// System topic subscription with minimal props - exercises resourceGroupName fallback
this.eventgridSystemEventSubscription = this.eventgridManager.createEventgridSystemTopicEventSubscription(
`test-minimal-eg-sys-sub-${this.props.stage}`,
this,
{
eventSubscriptionName: 'test-minimal-eg-sys-sub',
scope:
'/subscriptions/test-sub/resourceGroups/test-rg-dev/providers/Microsoft.EventGrid/systemTopics/test-minimal-eg-sys-topic-dev',
destination: {
endpointType: 'WebHook',
properties: { endpointUrl: 'https://test.example.com/webhook' },
},
} as any,
this.eventgridSystemTopic
)

this.resolvedEventgridTopic = this.eventgridManager.resolveEventgridTopic(
`test-resolved-eg-topic-${this.props.stage}`,
this,
{
topicName: 'test-minimal-eg-topic',
} as any
)

this.resolvedEventgridSystemTopic = this.eventgridManager.resolveEventgridSystemTopic(
`test-resolved-eg-sys-topic-${this.props.stage}`,
this,
{
systemTopicName: 'test-minimal-eg-sys-topic',
} as any
)
}
}

Expand Down Expand Up @@ -359,6 +402,26 @@ describe('TestAzureEventgridConstruct - Default Values', () => {
)
})

test('eventgrid topic uses default data residency boundary when not provided', async () => {
await outputToPromise(
pulumi
.all([minimalEventgridStack.construct.eventgridTopic.dataResidencyBoundary])
.apply(([dataResidencyBoundary]) => {
expect(dataResidencyBoundary).toEqual('WithinGeopair')
})
)
})

test('eventgrid topic uses default minimum tls version when not provided', async () => {
await outputToPromise(
pulumi
.all([minimalEventgridStack.construct.eventgridTopic.minimumTlsVersionAllowed])
.apply(([minimumTlsVersionAllowed]) => {
expect(minimumTlsVersionAllowed).toEqual('1.2')
})
)
})

test('eventgrid subscription uses default eventDeliverySchema when not provided', async () => {
await outputToPromise(
pulumi.all([minimalEventgridStack.construct.eventgridSubscription.eventDeliverySchema]).apply(([schema]) => {
Expand Down Expand Up @@ -391,4 +454,24 @@ describe('TestAzureEventgridConstruct - Default Values', () => {
})
)
})

test('resolve eventgrid topic uses formatted topic name and default resource group name from scope', async () => {
await outputToPromise(
pulumi.output(minimalEventgridStack.construct.resolvedEventgridTopic).apply(resolvedEventgridTopic => {
expect((resolvedEventgridTopic as any).topicName).toEqual('test-minimal-eg-topic-dev')
expect((resolvedEventgridTopic as any).resourceGroupName).toEqual('test-rg-dev')
})
)
})

test('resolve eventgrid system topic uses provided system topic name and default resource group name from scope', async () => {
await outputToPromise(
pulumi
.output(minimalEventgridStack.construct.resolvedEventgridSystemTopic)
.apply(resolvedEventgridSystemTopic => {
expect((resolvedEventgridSystemTopic as any).systemTopicName).toEqual('test-minimal-eg-sys-topic')
expect((resolvedEventgridSystemTopic as any).resourceGroupName).toEqual('test-rg-dev')
})
)
})
})