Skip to content

Commit a8f91b1

Browse files
authored
Support detecting event hubs by analyzing pom.xml and application.yml (#3)
* Support detect Azure Event Hubs: produce message only, managed identity only. * Support detect Azure Event Hubs: produce message only. Try to connect by connection string, but failed: Cant not get connection string. Issue created: Azure/bicep-registry-modules#3638 * Support detect Azure Event Hubs: produce message only, support both managed-identity and connection-string. * Change option from "Password" to "Connection string". * Rename "getAuthTypeByPrompt" to "chooseAuthType".
1 parent d1cd151 commit a8f91b1

File tree

8 files changed

+172
-21
lines changed

8 files changed

+172
-21
lines changed

cli/azd/internal/appdetect/appdetect.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,14 @@ func (a AzureDepServiceBus) ResourceDisplay() string {
145145
return "Azure Service Bus"
146146
}
147147

148+
type AzureDepEventHubs struct {
149+
Names []string
150+
}
151+
152+
func (a AzureDepEventHubs) ResourceDisplay() string {
153+
return "Azure Event Hubs"
154+
}
155+
148156
type Project struct {
149157
// The language associated with the project.
150158
Language Language

cli/azd/internal/appdetect/java.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,18 @@ func detectDependencies(mavenProject *mavenProject, project *Project) (*Project,
178178
Queues: destinations,
179179
})
180180
}
181+
182+
if dep.GroupId == "com.azure.spring" && dep.ArtifactId == "spring-cloud-azure-stream-binder-eventhubs" {
183+
bindingDestinations := findBindingDestinations(applicationProperties)
184+
destinations := make([]string, 0, len(bindingDestinations))
185+
for bindingName, destination := range bindingDestinations {
186+
destinations = append(destinations, destination)
187+
log.Printf("Event Hubs [%s] found for binding [%s]", destination, bindingName)
188+
}
189+
project.AzureDeps = append(project.AzureDeps, AzureDepEventHubs{
190+
Names: destinations,
191+
})
192+
}
181193
}
182194

183195
if len(databaseDepMap) > 0 {

cli/azd/internal/repository/app_init.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ var dbMap = map[appdetect.DatabaseDep]struct{}{
4141

4242
var azureDepMap = map[string]struct{}{
4343
appdetect.AzureDepServiceBus{}.ResourceDisplay(): {},
44+
appdetect.AzureDepEventHubs{}.ResourceDisplay(): {},
4445
}
4546

4647
// InitFromApp initializes the infra directory and project file from the current existing app.

cli/azd/internal/repository/infra_confirm.go

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ func (i *Initializer) infraSpecFromDetect(
212212
switch azureDep.(type) {
213213
case appdetect.AzureDepServiceBus:
214214
serviceSpec.AzureServiceBus = spec.AzureServiceBus
215+
case appdetect.AzureDepEventHubs:
216+
serviceSpec.AzureEventHubs = spec.AzureEventHubs
215217
}
216218
}
217219
spec.Services = append(spec.Services, serviceSpec)
@@ -344,41 +346,51 @@ azureDepPrompt:
344346
}
345347
}
346348

347-
authType := scaffold.AuthType(0)
348349
switch azureDep.(type) {
349350
case appdetect.AzureDepServiceBus:
350-
_authType, err := i.console.Prompt(ctx, input.ConsoleOptions{
351-
Message: fmt.Sprintf("Input the authentication type you want for (%s), 1 for connection string, 2 for managed identity", azureDep.ResourceDisplay()),
352-
Help: "Authentication type:\n\n" +
353-
"Enter 1 if you want to use connection string to connect to the Service Bus.\n" +
354-
"Enter 2 if you want to use user assigned managed identity to connect to the Service Bus.",
355-
})
351+
authType, err := i.chooseAuthType(ctx, azureDepName)
356352
if err != nil {
357353
return err
358354
}
359-
360-
if _authType != "1" && _authType != "2" {
361-
i.console.Message(ctx, "Invalid authentication type. Please enter 0 or 1.")
362-
continue azureDepPrompt
363-
}
364-
if _authType == "1" {
365-
authType = scaffold.AuthType_PASSWORD
366-
} else {
367-
authType = scaffold.AuthType_TOKEN_CREDENTIAL
368-
}
369-
}
370-
371-
switch azureDep.(type) {
372-
case appdetect.AzureDepServiceBus:
373355
spec.AzureServiceBus = &scaffold.AzureDepServiceBus{
374356
Name: azureDepName,
375357
Queues: azureDep.(appdetect.AzureDepServiceBus).Queues,
376358
AuthUsingConnectionString: authType == scaffold.AuthType_PASSWORD,
377359
AuthUsingManagedIdentity: authType == scaffold.AuthType_TOKEN_CREDENTIAL,
378360
}
361+
case appdetect.AzureDepEventHubs:
362+
authType, err := i.chooseAuthType(ctx, azureDepName)
363+
if err != nil {
364+
return err
365+
}
366+
spec.AzureEventHubs = &scaffold.AzureDepEventHubs{
367+
Name: azureDepName,
368+
EventHubNames: azureDep.(appdetect.AzureDepEventHubs).Names,
369+
AuthUsingConnectionString: authType == scaffold.AuthType_PASSWORD,
370+
AuthUsingManagedIdentity: authType == scaffold.AuthType_TOKEN_CREDENTIAL,
371+
}
379372
break azureDepPrompt
380373
}
381374
break azureDepPrompt
382375
}
383376
return nil
384377
}
378+
379+
func (i *Initializer) chooseAuthType(ctx context.Context, serviceName string) (scaffold.AuthType, error) {
380+
portOptions := []string{
381+
"User assigned managed identity",
382+
"Connection string",
383+
}
384+
selection, err := i.console.Select(ctx, input.ConsoleOptions{
385+
Message: "Choose auth type for '" + serviceName + "'?",
386+
Options: portOptions,
387+
})
388+
if err != nil {
389+
return scaffold.AUTH_TYPE_UNSPECIFIED, err
390+
}
391+
if selection == 0 {
392+
return scaffold.AuthType_TOKEN_CREDENTIAL, nil
393+
} else {
394+
return scaffold.AuthType_PASSWORD, nil
395+
}
396+
}

cli/azd/internal/scaffold/spec.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ type InfraSpec struct {
1717

1818
// Azure Service Bus
1919
AzureServiceBus *AzureDepServiceBus
20+
// Azure EventHubs
21+
AzureEventHubs *AzureDepEventHubs
2022
}
2123

2224
type Parameter struct {
@@ -55,6 +57,13 @@ type AzureDepServiceBus struct {
5557
AuthUsingManagedIdentity bool
5658
}
5759

60+
type AzureDepEventHubs struct {
61+
Name string
62+
EventHubNames []string
63+
AuthUsingConnectionString bool
64+
AuthUsingManagedIdentity bool
65+
}
66+
5867
// AuthType defines different authentication types.
5968
type AuthType int32
6069

@@ -84,6 +93,8 @@ type ServiceSpec struct {
8493

8594
// Azure Service Bus
8695
AzureServiceBus *AzureDepServiceBus
96+
// Azure Service Bus
97+
AzureEventHubs *AzureDepEventHubs
8798
}
8899

89100
type Frontend struct {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
param eventHubsNamespaceName string
2+
param connectionStringSecretName string
3+
param keyVaultName string
4+
5+
resource eventHubsNamespace 'Microsoft.EventHub/namespaces@2024-01-01' existing = {
6+
name: eventHubsNamespaceName
7+
}
8+
9+
resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
10+
name: keyVaultName
11+
}
12+
13+
resource connectionStringSecret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {
14+
name: connectionStringSecretName
15+
parent: keyVault
16+
properties: {
17+
value: listKeys(concat(resourceId('Microsoft.EventHub/namespaces', eventHubsNamespaceName), '/AuthorizationRules/RootManageSharedAccessKey'), '2024-01-01').primaryConnectionString
18+
}
19+
}
20+

cli/azd/resources/scaffold/templates/main.bicept

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,7 @@ output AZURE_CACHE_REDIS_ID string = resources.outputs.AZURE_CACHE_REDIS_ID
5959
{{- if .DbPostgres}}
6060
output AZURE_POSTGRES_FLEXIBLE_SERVER_ID string = resources.outputs.AZURE_POSTGRES_FLEXIBLE_SERVER_ID
6161
{{- end}}
62+
{{- if .AzureEventHubs }}
63+
output AZURE_EVENT_HUBS_ID string = resources.outputs.AZURE_EVENT_HUBS_ID
64+
{{- end}}
6265
{{ end}}

cli/azd/resources/scaffold/templates/resources.bicept

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,47 @@ module postgreServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:0.1.4
126126
}
127127
}
128128
{{- end}}
129+
{{- if .AzureEventHubs }}
129130

131+
module eventHubNamespace 'br/public:avm/res/event-hub/namespace:0.7.1' = {
132+
name: 'eventHubNamespace'
133+
params: {
134+
name: '${abbrs.eventHubNamespaces}${resourceToken}'
135+
location: location
136+
roleAssignments: [
137+
{{- if (and .AzureEventHubs .AzureEventHubs.AuthUsingManagedIdentity) }}
138+
{{- range .Services}}
139+
{
140+
principalId: {{bicepName .Name}}Identity.outputs.principalId
141+
principalType: 'ServicePrincipal'
142+
roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec')
143+
}
144+
{{- end}}
145+
{{- end}}
146+
]
147+
{{- if (and .AzureEventHubs .AzureEventHubs.AuthUsingConnectionString) }}
148+
disableLocalAuth: false
149+
{{- end}}
150+
eventhubs: [
151+
{{- range $eventHubName := .AzureEventHubs.EventHubNames}}
152+
{
153+
name: '{{ $eventHubName }}'
154+
}
155+
{{- end}}
156+
]
157+
}
158+
}
159+
{{- if (and .AzureEventHubs .AzureEventHubs.AuthUsingConnectionString) }}
160+
module eventHubsConnectionString './modules/set-event-hubs-namespace-connection-string.bicep' = {
161+
name: 'eventHubsConnectionString'
162+
params: {
163+
eventHubsNamespaceName: eventHubNamespace.outputs.name
164+
connectionStringSecretName: 'EVENT-HUBS-CONNECTION-STRING'
165+
keyVaultName: keyVault.outputs.name
166+
}
167+
}
168+
{{end}}
169+
{{end}}
130170
{{- range .Services}}
131171

132172
module {{bicepName .Name}}Identity 'br/public:avm/res/managed-identity/user-assigned-identity:0.2.1' = {
@@ -205,6 +245,13 @@ module {{bicepName .Name}} 'br/public:avm/res/app/container-app:0.8.0' = {
205245
keyVaultUrl: '${keyVault.outputs.uri}secrets/REDIS-URL'
206246
}
207247
{{- end}}
248+
{{- if (and .AzureEventHubs .AzureEventHubs.AuthUsingConnectionString) }}
249+
{
250+
name: 'event-hubs-connection-string'
251+
identity:{{bicepName .Name}}Identity.outputs.resourceId
252+
keyVaultUrl: '${keyVault.outputs.uri}secrets/EVENT-HUBS-CONNECTION-STRING'
253+
}
254+
{{- end}}
208255
],
209256
map({{bicepName .Name}}Secrets, secret => {
210257
name: secret.secretRef
@@ -282,6 +329,40 @@ module {{bicepName .Name}} 'br/public:avm/res/app/container-app:0.8.0' = {
282329
secretRef: 'redis-pass'
283330
}
284331
{{- end}}
332+
{{- if .AzureEventHubs }}
333+
{
334+
name: 'SPRING_CLOUD_AZURE_EVENTHUBS_NAMESPACE'
335+
value: eventHubNamespace.outputs.name
336+
}
337+
{{- end}}
338+
{{- if (and .AzureEventHubs .AzureEventHubs.AuthUsingManagedIdentity) }}
339+
{
340+
name: 'SPRING_CLOUD_AZURE_EVENTHUBS_CONNECTION_STRING'
341+
value: ''
342+
}
343+
{
344+
name: 'SPRING_CLOUD_AZURE_EVENTHUBS_CREDENTIAL_MANAGEDIDENTITYENABLED'
345+
value: 'true'
346+
}
347+
{
348+
name: 'SPRING_CLOUD_AZURE_EVENTHUBS_CREDENTIAL_CLIENTID'
349+
value: {{bicepName .Name}}Identity.outputs.clientId
350+
}
351+
{{- end}}
352+
{{- if (and .AzureEventHubs .AzureEventHubs.AuthUsingConnectionString) }}
353+
{
354+
name: 'SPRING_CLOUD_AZURE_EVENTHUBS_CONNECTION_STRING'
355+
secretRef: 'event-hubs-connection-string'
356+
}
357+
{
358+
name: 'SPRING_CLOUD_AZURE_EVENTHUBS_CREDENTIAL_MANAGEDIDENTITYENABLED'
359+
value: 'false'
360+
}
361+
{
362+
name: 'SPRING_CLOUD_AZURE_EVENTHUBS_CREDENTIAL_CLIENTID'
363+
value: ''
364+
}
365+
{{- end}}
285366
{{- if .Frontend}}
286367
{{- range $i, $e := .Frontend.Backends}}
287368
{
@@ -392,4 +473,7 @@ output AZURE_CACHE_REDIS_ID string = redis.outputs.resourceId
392473
{{- if .DbPostgres}}
393474
output AZURE_POSTGRES_FLEXIBLE_SERVER_ID string = postgreServer.outputs.resourceId
394475
{{- end}}
476+
{{- if .AzureEventHubs }}
477+
output AZURE_EVENT_HUBS_ID string = eventHubNamespace.outputs.resourceId
478+
{{- end}}
395479
{{ end}}

0 commit comments

Comments
 (0)