From 7b7739d9f527322e42861d951031d3cc82cde039 Mon Sep 17 00:00:00 2001 From: hemarina Date: Wed, 24 Jan 2024 17:33:07 -0800 Subject: [PATCH 01/21] add support on sql --- cli/azd/pkg/apphost/generate.go | 28 ++++++++++-- cli/azd/pkg/apphost/generate_types.go | 5 +++ .../resources/apphost/templates/main.bicept | 5 +++ .../apphost/templates/resources.bicept | 44 +++++++++++++++++++ 4 files changed, 78 insertions(+), 4 deletions(-) diff --git a/cli/azd/pkg/apphost/generate.go b/cli/azd/pkg/apphost/generate.go index c7c0dcc44d8..6235d9c1412 100644 --- a/cli/azd/pkg/apphost/generate.go +++ b/cli/azd/pkg/apphost/generate.go @@ -23,7 +23,7 @@ const RedisContainerAppService = "redis" const DaprStateStoreComponentType = "state" const DaprPubSubComponentType = "pubsub" -const containerAppSecretConnectionString = "{{ connectionString " +const containerAppSecretConnectionString = "{{ connectionString }}" // genTemplates is the collection of templates that are used when generating infrastructure files from a manifest. var genTemplates *template.Template @@ -260,6 +260,7 @@ func newInfraGenerator() *infraGenerator { ContainerApps: make(map[string]genContainerApp), DaprComponents: make(map[string]genDaprComponent), CosmosDbAccounts: make(map[string]genCosmosAccount), + SqlServers: make(map[string]genSqlServer), }, containers: make(map[string]genContainer), dapr: make(map[string]genDapr), @@ -342,6 +343,10 @@ func (b *infraGenerator) LoadManifest(m *Manifest) error { b.addCosmosDbAccount(name) case "azure.cosmosdb.database.v0": b.addCosmosDatabase(*comp.Parent, name) + case "azure.sql.v0", "sqlserver.server.v0", "sqlserver.server.v1": + b.addSqlServers(name) + case "azure.sql.database.v0", "sqlserver.database.v0", "sqlserver.database.v1": + b.addSqlDatabase(*comp.Parent, name) case "postgres.server.v0": // We currently use a ACA Postgres Service per database. Because of this, we don't need to retain any // information from the server resource. @@ -350,7 +355,7 @@ func (b *infraGenerator) LoadManifest(m *Manifest) error { // resource type. case "postgres.database.v0": b.addContainerAppService(name, "postgres") - case "postgres.connection.v0", "rabbitmq.connection.v0", "azure.cosmosdb.connection.v0": + case "postgres.connection.v0", "rabbitmq.connection.v0", "azure.cosmosdb.connection.v0", "sqlserver.connection.v0": // Only interesting thing about the connection resource is the connection string, which we handle above. // We have the case statement here to ensure we don't error out on the resource type by treating it as an unknown @@ -426,6 +431,18 @@ func (b *infraGenerator) addCosmosDatabase(cosmosDbAccount, dbName string) { b.bicepContext.CosmosDbAccounts[cosmosDbAccount] = account } +func (b *infraGenerator) addSqlServers(name string) { + if _, exists := b.bicepContext.SqlServers[name]; !exists { + b.bicepContext.SqlServers[name] = genSqlServer{} + } +} + +func (b *infraGenerator) addSqlDatabase(sqlAccount, dbName string) { + account := b.bicepContext.SqlServers[sqlAccount] + account.Databases = append(account.Databases, dbName) + b.bicepContext.SqlServers[sqlAccount] = account +} + func (b *infraGenerator) addProject( name string, path string, env map[string]string, bindings map[string]*Binding, ) { @@ -885,7 +902,9 @@ func (b infraGenerator) evalBindingRef(v string, emitType inputEmitType) (string case targetType == "postgres.database.v0" || targetType == "redis.v0" || targetType == "azure.cosmosdb.account.v0" || - targetType == "azure.cosmosdb.database.v0": + targetType == "azure.cosmosdb.database.v0" || + targetType == "azure.sql.v0" || + targetType == "azure.sql.database.v0": switch prop { case "connectionString": // returns something like {{ connectionString "resource" }} @@ -909,7 +928,8 @@ func (b infraGenerator) evalBindingRef(v string, emitType inputEmitType) (string } case targetType == "azure.cosmosdb.connection.v0" || targetType == "postgres.connection.v0" || - targetType == "rabbitmq.connection.v0": + targetType == "rabbitmq.connection.v0" || + targetType == "sqlserver.connection.v0": switch prop { case "connectionString": diff --git a/cli/azd/pkg/apphost/generate_types.go b/cli/azd/pkg/apphost/generate_types.go index 7f535120cdc..e877e706074 100644 --- a/cli/azd/pkg/apphost/generate_types.go +++ b/cli/azd/pkg/apphost/generate_types.go @@ -88,6 +88,10 @@ type genInput struct { DefaultMinLength int } +type genSqlServer struct { + Databases []string +} + type genBicepTemplateContext struct { HasContainerRegistry bool HasContainerEnvironment bool @@ -101,6 +105,7 @@ type genBicepTemplateContext struct { ContainerApps map[string]genContainerApp DaprComponents map[string]genDaprComponent CosmosDbAccounts map[string]genCosmosAccount + SqlServers map[string]genSqlServer } type genContainerAppManifestTemplateContext struct { diff --git a/cli/azd/resources/apphost/templates/main.bicept b/cli/azd/resources/apphost/templates/main.bicept index 2b6bee7349f..7a076081f5b 100644 --- a/cli/azd/resources/apphost/templates/main.bicept +++ b/cli/azd/resources/apphost/templates/main.bicept @@ -66,4 +66,9 @@ output SERVICE_BINDING_{{alphaSnakeUpper $name}}_ENDPOINT string = resources.out {{range $name, $value := .CosmosDbAccounts -}} output SERVICE_BINDING_{{alphaSnakeUpper $name}}_NAME string = resources.outputs.SERVICE_BINDING_{{alphaSnakeUpper $name}}_NAME {{end -}} +{{range $name, $value := .SqlServers -}} +{{range $cname := $value.Databases -}} +output SERVICE_BINDING_{{alphaSnakeUpper $name}}_CONNECTION_STRING string = resources.outputs.SERVICE_BINDING_{{alphaSnakeUpper $cname}}_CONNECTION_STRING +{{end -}} +{{end -}} {{ end}} \ No newline at end of file diff --git a/cli/azd/resources/apphost/templates/resources.bicept b/cli/azd/resources/apphost/templates/resources.bicept index 050dd5f16aa..4a4f055a3ee 100644 --- a/cli/azd/resources/apphost/templates/resources.bicept +++ b/cli/azd/resources/apphost/templates/resources.bicept @@ -325,6 +325,7 @@ resource {{bicepName $name}} 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' ] databaseAccountOfferType: 'Standard' } +} {{range $cname := $value.Databases}} resource {{bicepName $cname}} 'sqlDatabases@2023-04-15' = { name: '{{$cname}}' @@ -337,7 +338,45 @@ resource {{bicepName $name}} 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' } } {{end -}} +{{end -}} +{{range $name, $value := .SqlServers}} +resource {{bicepName $name}} 'Microsoft.Sql/servers@2022-05-01-preview' = { + name: '{{$name}}-${resourceToken}' + location: location + tags: union(tags, {'aspire-resource-name': '{{$name}}'}) + properties: { + minimalTlsVersion: '1.2' + publicNetworkAccess: 'Enabled' + administrators: { + administratorType: 'ActiveDirectory' + azureADOnlyAuthentication: true + login: managedIdentity.name + principalType: 'User' + sid: managedIdentity.properties.principalId + tenantId: subscription().tenantId + } + } } + +resource {{bicepName $name}}Firewall 'Microsoft.Sql/servers/firewallRules@2022-05-01-preview' = { + name: 'fw-{{$name}}-${resourceToken}' + parent: {{bicepName $name}} + properties: { + startIpAddress: '0.0.0.0' + endIpAddress: '255.255.255.255' + } +} + {{range $cname := $value.Databases}} + resource {{bicepName $cname}} 'Microsoft.Sql/servers/databases@2022-05-01-preview' = { + name: '{{$cname}}' + parent: {{bicepName $name}} + location: location + sku: { + name: 'S0' + } + tags: union(tags, {'aspire-resource-name': '{{$cname}}'}) + } +{{end -}} {{end -}} output MANAGED_IDENTITY_CLIENT_ID string = managedIdentity.properties.clientId {{if .HasContainerRegistry -}} @@ -371,4 +410,9 @@ output SERVICE_BINDING_{{alphaSnakeUpper $name}}_ENDPOINT string = {{bicepName $ {{range $name, $value := .CosmosDbAccounts -}} output SERVICE_BINDING_{{alphaSnakeUpper $name}}_NAME string = {{bicepName $name}}.name {{end -}} +{{range $name, $value := .SqlServers -}} +{{range $cname := $value.Databases -}} +output SERVICE_BINDING_{{alphaSnakeUpper $cname}}_CONNECTION_STRING string = 'Server=tcp:{{bicepName $name}}.Data.FullyQualifiedDomainName,1433;Initial Catalog={{bicepName $cname}};Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;Authentication=\'Active Directory Default\';' +{{end -}} +{{end -}} {{ end}} \ No newline at end of file From 8a06ef843ca8dc10753b7f292b35ce6d1a912db8 Mon Sep 17 00:00:00 2001 From: hemarina Date: Wed, 24 Jan 2024 18:01:28 -0800 Subject: [PATCH 02/21] remove this case --- cli/azd/pkg/apphost/generate.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cli/azd/pkg/apphost/generate.go b/cli/azd/pkg/apphost/generate.go index 6235d9c1412..a3509909946 100644 --- a/cli/azd/pkg/apphost/generate.go +++ b/cli/azd/pkg/apphost/generate.go @@ -928,8 +928,7 @@ func (b infraGenerator) evalBindingRef(v string, emitType inputEmitType) (string } case targetType == "azure.cosmosdb.connection.v0" || targetType == "postgres.connection.v0" || - targetType == "rabbitmq.connection.v0" || - targetType == "sqlserver.connection.v0": + targetType == "rabbitmq.connection.v0": switch prop { case "connectionString": From 635ee0883b519675c87951db6dfc8ca8677bc0e7 Mon Sep 17 00:00:00 2001 From: hemarina Date: Wed, 24 Jan 2024 18:08:32 -0800 Subject: [PATCH 03/21] remove unwanted }} --- cli/azd/pkg/apphost/generate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/azd/pkg/apphost/generate.go b/cli/azd/pkg/apphost/generate.go index a3509909946..b5d8be186ca 100644 --- a/cli/azd/pkg/apphost/generate.go +++ b/cli/azd/pkg/apphost/generate.go @@ -23,7 +23,7 @@ const RedisContainerAppService = "redis" const DaprStateStoreComponentType = "state" const DaprPubSubComponentType = "pubsub" -const containerAppSecretConnectionString = "{{ connectionString }}" +const containerAppSecretConnectionString = "{{ connectionString " // genTemplates is the collection of templates that are used when generating infrastructure files from a manifest. var genTemplates *template.Template From 3ac0428515e921df00d57426b89d2a114285cff4 Mon Sep 17 00:00:00 2001 From: hemarina Date: Wed, 24 Jan 2024 18:45:20 -0800 Subject: [PATCH 04/21] remove --- cli/azd/pkg/apphost/generate.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cli/azd/pkg/apphost/generate.go b/cli/azd/pkg/apphost/generate.go index b5d8be186ca..e8108677078 100644 --- a/cli/azd/pkg/apphost/generate.go +++ b/cli/azd/pkg/apphost/generate.go @@ -902,9 +902,7 @@ func (b infraGenerator) evalBindingRef(v string, emitType inputEmitType) (string case targetType == "postgres.database.v0" || targetType == "redis.v0" || targetType == "azure.cosmosdb.account.v0" || - targetType == "azure.cosmosdb.database.v0" || - targetType == "azure.sql.v0" || - targetType == "azure.sql.database.v0": + targetType == "azure.cosmosdb.database.v0": switch prop { case "connectionString": // returns something like {{ connectionString "resource" }} From a387d668d608c33cd81a75b5534fec740469323b Mon Sep 17 00:00:00 2001 From: hemarina Date: Wed, 24 Jan 2024 22:48:47 -0800 Subject: [PATCH 05/21] debug --- cli/azd/pkg/apphost/generate.go | 12 ++++++++---- cli/azd/resources/apphost/templates/main.bicept | 2 +- cli/azd/resources/apphost/templates/resources.bicept | 5 ++++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/cli/azd/pkg/apphost/generate.go b/cli/azd/pkg/apphost/generate.go index e8108677078..e4d8ac36a3c 100644 --- a/cli/azd/pkg/apphost/generate.go +++ b/cli/azd/pkg/apphost/generate.go @@ -917,17 +917,21 @@ func (b infraGenerator) evalBindingRef(v string, emitType inputEmitType) (string default: return "", errUnsupportedProperty("azure.servicebus.v0", prop) } - case targetType == "azure.appinsights.v0": + case targetType == "azure.appinsights.v0" || + targetType == "azure.sql.database.v0" || + targetType == "sqlserver.database.v0" || + targetType == "sqlserver.database.v1": switch prop { case "connectionString": return fmt.Sprintf("{{ .Env.SERVICE_BINDING_%s_CONNECTION_STRING }}", scaffold.AlphaSnakeUpper(resource)), nil default: - return "", errUnsupportedProperty("azure.appinsights.v0", prop) + return "", errUnsupportedProperty(targetType, prop) } case targetType == "azure.cosmosdb.connection.v0" || targetType == "postgres.connection.v0" || - targetType == "rabbitmq.connection.v0": - + targetType == "rabbitmq.connection.v0" || + targetType == "sqlserver.connection.v0" || + targetType == "sqlserver.connection.v1": switch prop { case "connectionString": return b.connectionStrings[resource], nil diff --git a/cli/azd/resources/apphost/templates/main.bicept b/cli/azd/resources/apphost/templates/main.bicept index 7a076081f5b..630b141a1fb 100644 --- a/cli/azd/resources/apphost/templates/main.bicept +++ b/cli/azd/resources/apphost/templates/main.bicept @@ -68,7 +68,7 @@ output SERVICE_BINDING_{{alphaSnakeUpper $name}}_NAME string = resources.outputs {{end -}} {{range $name, $value := .SqlServers -}} {{range $cname := $value.Databases -}} -output SERVICE_BINDING_{{alphaSnakeUpper $name}}_CONNECTION_STRING string = resources.outputs.SERVICE_BINDING_{{alphaSnakeUpper $cname}}_CONNECTION_STRING +output SERVICE_BINDING_{{alphaSnakeUpper $cname}}_CONNECTION_STRING string = resources.outputs.SERVICE_BINDING_{{alphaSnakeUpper $cname}}_CONNECTION_STRING {{end -}} {{end -}} {{ end}} \ No newline at end of file diff --git a/cli/azd/resources/apphost/templates/resources.bicept b/cli/azd/resources/apphost/templates/resources.bicept index 4a4f055a3ee..86f58179e5f 100644 --- a/cli/azd/resources/apphost/templates/resources.bicept +++ b/cli/azd/resources/apphost/templates/resources.bicept @@ -338,7 +338,9 @@ resource {{bicepName $name}} 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' } } {{end -}} + {{end -}} + {{range $name, $value := .SqlServers}} resource {{bicepName $name}} 'Microsoft.Sql/servers@2022-05-01-preview' = { name: '{{$name}}-${resourceToken}' @@ -359,13 +361,14 @@ resource {{bicepName $name}} 'Microsoft.Sql/servers@2022-05-01-preview' = { } resource {{bicepName $name}}Firewall 'Microsoft.Sql/servers/firewallRules@2022-05-01-preview' = { - name: 'fw-{{$name}}-${resourceToken}' + name: 'fw-{{$name}}' parent: {{bicepName $name}} properties: { startIpAddress: '0.0.0.0' endIpAddress: '255.255.255.255' } } + {{range $cname := $value.Databases}} resource {{bicepName $cname}} 'Microsoft.Sql/servers/databases@2022-05-01-preview' = { name: '{{$cname}}' From b993494cc9c45f1fd46e5010f267aa1c3a4b4031 Mon Sep 17 00:00:00 2001 From: hemarina Date: Thu, 25 Jan 2024 15:04:21 -0800 Subject: [PATCH 06/21] change function name and nest resources under sql/server --- cli/azd/pkg/apphost/generate.go | 16 +++++++++------- .../resources/apphost/templates/resources.bicept | 6 +++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/cli/azd/pkg/apphost/generate.go b/cli/azd/pkg/apphost/generate.go index e8108677078..f8d91fba81f 100644 --- a/cli/azd/pkg/apphost/generate.go +++ b/cli/azd/pkg/apphost/generate.go @@ -23,7 +23,7 @@ const RedisContainerAppService = "redis" const DaprStateStoreComponentType = "state" const DaprPubSubComponentType = "pubsub" -const containerAppSecretConnectionString = "{{ connectionString " +const containerAppSecretConnectionString = "{{ connectionString }}" // genTemplates is the collection of templates that are used when generating infrastructure files from a manifest. var genTemplates *template.Template @@ -344,7 +344,7 @@ func (b *infraGenerator) LoadManifest(m *Manifest) error { case "azure.cosmosdb.database.v0": b.addCosmosDatabase(*comp.Parent, name) case "azure.sql.v0", "sqlserver.server.v0", "sqlserver.server.v1": - b.addSqlServers(name) + b.addSqlServer(name) case "azure.sql.database.v0", "sqlserver.database.v0", "sqlserver.database.v1": b.addSqlDatabase(*comp.Parent, name) case "postgres.server.v0": @@ -355,7 +355,7 @@ func (b *infraGenerator) LoadManifest(m *Manifest) error { // resource type. case "postgres.database.v0": b.addContainerAppService(name, "postgres") - case "postgres.connection.v0", "rabbitmq.connection.v0", "azure.cosmosdb.connection.v0", "sqlserver.connection.v0": + case "postgres.connection.v0", "rabbitmq.connection.v0", "azure.cosmosdb.connection.v0": // Only interesting thing about the connection resource is the connection string, which we handle above. // We have the case statement here to ensure we don't error out on the resource type by treating it as an unknown @@ -431,7 +431,7 @@ func (b *infraGenerator) addCosmosDatabase(cosmosDbAccount, dbName string) { b.bicepContext.CosmosDbAccounts[cosmosDbAccount] = account } -func (b *infraGenerator) addSqlServers(name string) { +func (b *infraGenerator) addSqlServer(name string) { if _, exists := b.bicepContext.SqlServers[name]; !exists { b.bicepContext.SqlServers[name] = genSqlServer{} } @@ -902,7 +902,10 @@ func (b infraGenerator) evalBindingRef(v string, emitType inputEmitType) (string case targetType == "postgres.database.v0" || targetType == "redis.v0" || targetType == "azure.cosmosdb.account.v0" || - targetType == "azure.cosmosdb.database.v0": + targetType == "azure.cosmosdb.database.v0" || + targetType == "azure.sql.database.v0" || + targetType == "sqlserver.database.v0" || + targetType == "sqlserver.database.v1": switch prop { case "connectionString": // returns something like {{ connectionString "resource" }} @@ -922,12 +925,11 @@ func (b infraGenerator) evalBindingRef(v string, emitType inputEmitType) (string case "connectionString": return fmt.Sprintf("{{ .Env.SERVICE_BINDING_%s_CONNECTION_STRING }}", scaffold.AlphaSnakeUpper(resource)), nil default: - return "", errUnsupportedProperty("azure.appinsights.v0", prop) + return "", errUnsupportedProperty(targetType, prop) } case targetType == "azure.cosmosdb.connection.v0" || targetType == "postgres.connection.v0" || targetType == "rabbitmq.connection.v0": - switch prop { case "connectionString": return b.connectionStrings[resource], nil diff --git a/cli/azd/resources/apphost/templates/resources.bicept b/cli/azd/resources/apphost/templates/resources.bicept index 4a4f055a3ee..6db5d9ba163 100644 --- a/cli/azd/resources/apphost/templates/resources.bicept +++ b/cli/azd/resources/apphost/templates/resources.bicept @@ -358,8 +358,8 @@ resource {{bicepName $name}} 'Microsoft.Sql/servers@2022-05-01-preview' = { } } -resource {{bicepName $name}}Firewall 'Microsoft.Sql/servers/firewallRules@2022-05-01-preview' = { - name: 'fw-{{$name}}-${resourceToken}' +resource {{bicepName $name}}Firewall 'firewallRules@2022-05-01-preview' = { + name: 'fw-{{$name}}' parent: {{bicepName $name}} properties: { startIpAddress: '0.0.0.0' @@ -367,7 +367,7 @@ resource {{bicepName $name}}Firewall 'Microsoft.Sql/servers/firewallRules@2022-0 } } {{range $cname := $value.Databases}} - resource {{bicepName $cname}} 'Microsoft.Sql/servers/databases@2022-05-01-preview' = { + resource {{bicepName $cname}} 'databases@2022-05-01-preview' = { name: '{{$cname}}' parent: {{bicepName $name}} location: location From 42bad4ed390e0b567640593439263254861b320b Mon Sep 17 00:00:00 2001 From: hemarina Date: Thu, 25 Jan 2024 17:19:24 -0800 Subject: [PATCH 07/21] use containerAppSecretConnectionString instead of directly output --- cli/azd/pkg/azd/default.go | 4 + .../service_target_dotnet_containerapp.go | 27 ++++++- cli/azd/pkg/sqldb/sqldb.go | 75 +++++++++++++++++++ .../resources/apphost/templates/main.bicept | 4 +- .../apphost/templates/resources.bicept | 4 +- go.mod | 1 + go.sum | 2 + 7 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 cli/azd/pkg/sqldb/sqldb.go diff --git a/cli/azd/pkg/azd/default.go b/cli/azd/pkg/azd/default.go index fa9aeddbebe..404827e3078 100644 --- a/cli/azd/pkg/azd/default.go +++ b/cli/azd/pkg/azd/default.go @@ -15,6 +15,7 @@ import ( "github.com/azure/azure-dev/cli/azd/pkg/ioc" "github.com/azure/azure-dev/cli/azd/pkg/platform" "github.com/azure/azure-dev/cli/azd/pkg/project" + "github.com/azure/azure-dev/cli/azd/pkg/sqldb" "github.com/azure/azure-dev/cli/azd/pkg/state" "github.com/azure/azure-dev/cli/azd/pkg/templates" "github.com/azure/azure-dev/cli/azd/pkg/tools/bicep" @@ -117,6 +118,9 @@ func (p *DefaultPlatform) ConfigureContainer(container *ioc.NestedContainer) err }) container.RegisterSingleton(cosmosdb.NewCosmosDbService) + // sqldb + container.RegisterSingleton(sqldb.NewSqlDbService) + // Templates // Gets a list of default template sources used in azd. diff --git a/cli/azd/pkg/project/service_target_dotnet_containerapp.go b/cli/azd/pkg/project/service_target_dotnet_containerapp.go index 174e9bb81ac..9df7955d085 100644 --- a/cli/azd/pkg/project/service_target_dotnet_containerapp.go +++ b/cli/azd/pkg/project/service_target_dotnet_containerapp.go @@ -23,6 +23,7 @@ import ( "github.com/azure/azure-dev/cli/azd/pkg/environment" "github.com/azure/azure-dev/cli/azd/pkg/infra" "github.com/azure/azure-dev/cli/azd/pkg/password" + "github.com/azure/azure-dev/cli/azd/pkg/sqldb" "github.com/azure/azure-dev/cli/azd/pkg/tools" "github.com/azure/azure-dev/cli/azd/pkg/tools/dotnet" ) @@ -34,6 +35,7 @@ type dotnetContainerAppTarget struct { resourceManager ResourceManager dotNetCli dotnet.DotNetCli cosmosDbService cosmosdb.CosmosDbService + sqlDbService sqldb.SqlDbService } // NewDotNetContainerAppTarget creates the Service Target for a Container App that is written in .NET. Unlike @@ -51,6 +53,7 @@ func NewDotNetContainerAppTarget( resourceManager ResourceManager, dotNetCli dotnet.DotNetCli, cosmosDbService cosmosdb.CosmosDbService, + sqlDbService sqldb.SqlDbService, ) ServiceTarget { return &dotnetContainerAppTarget{ env: env, @@ -59,6 +62,7 @@ func NewDotNetContainerAppTarget( resourceManager: resourceManager, dotNetCli: dotNetCli, cosmosDbService: cosmosDbService, + sqlDbService: sqlDbService, } } @@ -184,6 +188,7 @@ func (at *dotnetContainerAppTarget) Deploy( targetResource: targetResource, containerAppService: at.containerAppService, cosmosDbService: at.cosmosDbService, + sqlDbService: at.sqlDbService, env: at.env, } @@ -351,6 +356,7 @@ type containerAppTemplateManifestFuncs struct { targetResource *environment.TargetResource containerAppService containerapps.ContainerAppService cosmosDbService cosmosdb.CosmosDbService + sqlDbService sqldb.SqlDbService env *environment.Environment } @@ -366,7 +372,7 @@ func (_ *containerAppTemplateManifestFuncs) UrlHost(s string) (string, error) { } // ConnectionString returns the connection string for the given resource name. Presently, we only support resources of -// type `redis.v0`, `postgres.v0` and `cosmosdb.database.v0`. +// type `redis.v0`, `postgres.v0`, `cosmosdb.database.v0`, `azure.sql.database.v0` and `sqlserver.database.v0`. // // It is callable from a template under the name `connectionString`. func (fns *containerAppTemplateManifestFuncs) ConnectionString(name string) (string, error) { @@ -407,6 +413,10 @@ func (fns *containerAppTemplateManifestFuncs) ConnectionString(name string) (str case "azure.cosmosdb.database.v0": // get the parent resource name, which is the cosmos account name return fns.cosmosConnectionString(*resource.Parent) + case "azure.sql.account.v0", "sqlserver.account.v0": + return fns.sqlConnectionString(name, "") + case "azure.sql.database.v0", "sqlserver.database.v0", "sqlserver.database.v1": + return fns.sqlConnectionString(*resource.Parent, name) default: return "", fmt.Errorf("connectionString: unsupported resource type '%s'", resource.Type) } @@ -428,6 +438,21 @@ func (fns *containerAppTemplateManifestFuncs) cosmosConnectionString(accountName resourceName) } +func (fns *containerAppTemplateManifestFuncs) sqlConnectionString(serverName string, sqlDbName string) (string, error) { + serverNameKey := fmt.Sprintf("SERVICE_BINDING_%s_NAME", scaffold.AlphaSnakeUpper(serverName)) + resourceName := fns.env.Getenv(serverNameKey) + if resourceName == "" { + return "", fmt.Errorf("the value for SERVICE_BINDING_%s_NAME was not found or is empty", serverName) + } + + return fns.sqlDbService.ConnectionString( + fns.ctx, + fns.targetResource.SubscriptionId(), + fns.targetResource.ResourceGroupName(), + resourceName, + sqlDbName) +} + // secretValue returns the value of the secret with the given name, or an error if the secret is not found. A nil value // is returned as "", without an error. func (fns *containerAppTemplateManifestFuncs) secretValue(containerAppName string, secretName string) (string, error) { diff --git a/cli/azd/pkg/sqldb/sqldb.go b/cli/azd/pkg/sqldb/sqldb.go new file mode 100644 index 00000000000..556fc8f4d1d --- /dev/null +++ b/cli/azd/pkg/sqldb/sqldb.go @@ -0,0 +1,75 @@ +package sqldb + +import ( + "context" + "fmt" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/sql/armsql/v2" +) + +// SqlDbService is the interface for the SqlDbService +type SqlDbService interface { + ConnectionString(ctx context.Context, subId, rgName, serverName string, dbName string) (string, error) +} + +type sqlDbClient struct { + credential azcore.TokenCredential + options *arm.ClientOptions +} + +// NewSqlDbService creates a new instance of the SqlDbService +func NewSqlDbService( + credential azcore.TokenCredential, + options *arm.ClientOptions, +) (SqlDbService, error) { + return &sqlDbClient{ + credential: credential, + options: options, + }, nil +} + +// ConnectionString returns the connection string for the CosmosDB account +func (c *sqlDbClient) ConnectionString(ctx context.Context, subId, rgName, serverName string, dbName string) (string, error) { + clientFactory, err := armsql.NewClientFactory(subId, c.credential, c.options) + if err != nil { + return "", err + } + + // Will delete this if not using: get list of databases for the server + // dbs := []armsql.Database{} + // pager := clientFactory.NewDatabasesClient().NewListByServerPager(rgName, serverName, &armsql.DatabasesClientListByServerOptions{SkipToken: nil}) + // for pager.More() { + // page, err := pager.NextPage(ctx) + // if err != nil { + // return "", fmt.Errorf("failed getting next page of databases: %w", err) + // } + + // for _, db := range page.DatabaseListResult.Value { + // if db != nil && db.Name != nil { + // dbs = append(dbs, *db) + // } + // } + + // } + + // get server fully qualified domain name + res, err := clientFactory.NewServersClient().Get(ctx, rgName, serverName, &armsql.ServersClientGetOptions{Expand: nil}) + if err != nil { + return "", fmt.Errorf("failed getting server '%s' for resource group '%s'", serverName, rgName) + } + + serverDomain := *res.Properties.FullyQualifiedDomainName + + if serverDomain == "" { + return "", fmt.Errorf("failed getting fully qualified domain name from server '%s'", serverName) + } + + // connection string for the server with no database + if dbName == "" { + return fmt.Sprintf("Server=tcp:%s,1433;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;Authentication=\"Active Directory Default\";", serverDomain), nil + } + + return fmt.Sprintf("Server=tcp:%s,1433;Encrypt=True;Initial Catalog=%s;TrustServerCertificate=False;Connection Timeout=30;Authentication=\"Active Directory Default\";", serverDomain, dbName), nil +} diff --git a/cli/azd/resources/apphost/templates/main.bicept b/cli/azd/resources/apphost/templates/main.bicept index 630b141a1fb..567403b4e8e 100644 --- a/cli/azd/resources/apphost/templates/main.bicept +++ b/cli/azd/resources/apphost/templates/main.bicept @@ -67,8 +67,6 @@ output SERVICE_BINDING_{{alphaSnakeUpper $name}}_ENDPOINT string = resources.out output SERVICE_BINDING_{{alphaSnakeUpper $name}}_NAME string = resources.outputs.SERVICE_BINDING_{{alphaSnakeUpper $name}}_NAME {{end -}} {{range $name, $value := .SqlServers -}} -{{range $cname := $value.Databases -}} -output SERVICE_BINDING_{{alphaSnakeUpper $cname}}_CONNECTION_STRING string = resources.outputs.SERVICE_BINDING_{{alphaSnakeUpper $cname}}_CONNECTION_STRING -{{end -}} +output SERVICE_BINDING_{{alphaSnakeUpper $name}}_NAME string = resources.outputs.SERVICE_BINDING_{{alphaSnakeUpper $name}}_NAME {{end -}} {{ end}} \ No newline at end of file diff --git a/cli/azd/resources/apphost/templates/resources.bicept b/cli/azd/resources/apphost/templates/resources.bicept index 534eb9ba20c..14c180b5543 100644 --- a/cli/azd/resources/apphost/templates/resources.bicept +++ b/cli/azd/resources/apphost/templates/resources.bicept @@ -414,8 +414,6 @@ output SERVICE_BINDING_{{alphaSnakeUpper $name}}_ENDPOINT string = {{bicepName $ output SERVICE_BINDING_{{alphaSnakeUpper $name}}_NAME string = {{bicepName $name}}.name {{end -}} {{range $name, $value := .SqlServers -}} -{{range $cname := $value.Databases -}} -output SERVICE_BINDING_{{alphaSnakeUpper $cname}}_CONNECTION_STRING string = 'Server=tcp:{{bicepName $name}}.Data.FullyQualifiedDomainName,1433;Initial Catalog={{bicepName $cname}};Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;Authentication=\'Active Directory Default\';' -{{end -}} +output SERVICE_BINDING_{{alphaSnakeUpper $name}}_NAME string = {{bicepName $name}}.name {{end -}} {{ end}} \ No newline at end of file diff --git a/go.mod b/go.mod index 49479be5750..09804e8800b 100644 --- a/go.mod +++ b/go.mod @@ -68,6 +68,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/apimanagement/armapimanagement v1.0.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/appconfiguration/armappconfiguration v1.0.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/sql/armsql/v2 v2.0.0-beta.4 github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cli/browser v1.1.0 diff --git a/go.sum b/go.sum index 64fae6335bb..164f98ee3f2 100644 --- a/go.sum +++ b/go.sum @@ -95,6 +95,8 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1. github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1/go.mod h1:c/wcGeGx5FUPbM/JltUYHZcKmigwyVLJlDq+4HdtXaw= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions v1.0.0 h1:xXmHA6JxGDHOY2anNQhpgIibZOiEaOvPLZOiAs07/4k= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions v1.0.0/go.mod h1:qkZjuhvy20x2Ckq4BzopZ8UjZLhib6nRJbRQiC6EFXY= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/sql/armsql/v2 v2.0.0-beta.4 h1:REtDJygCJQ4IkwgSOAY3CUpI1+AWKuOVP3jIGPYYiPk= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/sql/armsql/v2 v2.0.0-beta.4/go.mod h1:mXe/tbvI454sWulmm+3N5fkEs+yDvbQsA+8Xqr1kEQo= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0 h1:Ma67P/GGprNwsslzEH6+Kb8nybI8jpDTm4Wmzu2ReK8= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0/go.mod h1:c+Lifp3EDEamAkPVzMooRNOK6CZjNSdEnf1A7jsI9u4= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v0.13.0 h1:XY0plaTx8oeipK+XogAck2Qzv39KdnJNBwrxC4A0GL4= From c291bdfe49012118a69392f4ed07dd97d3699d4d Mon Sep 17 00:00:00 2001 From: hemarina Date: Thu, 25 Jan 2024 21:38:13 -0800 Subject: [PATCH 08/21] debug --- cli/azd/pkg/apphost/generate.go | 2 +- cli/azd/pkg/sqldb/sqldb.go | 19 +------------------ .../apphost/templates/resources.bicept | 2 +- 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/cli/azd/pkg/apphost/generate.go b/cli/azd/pkg/apphost/generate.go index 6cb1e029678..d2d7d6050c7 100644 --- a/cli/azd/pkg/apphost/generate.go +++ b/cli/azd/pkg/apphost/generate.go @@ -23,7 +23,7 @@ const RedisContainerAppService = "redis" const DaprStateStoreComponentType = "state" const DaprPubSubComponentType = "pubsub" -const containerAppSecretConnectionString = "{{ connectionString }}" +const containerAppSecretConnectionString = "{{ connectionString " // genTemplates is the collection of templates that are used when generating infrastructure files from a manifest. var genTemplates *template.Template diff --git a/cli/azd/pkg/sqldb/sqldb.go b/cli/azd/pkg/sqldb/sqldb.go index 556fc8f4d1d..f4c8d3f08c0 100644 --- a/cli/azd/pkg/sqldb/sqldb.go +++ b/cli/azd/pkg/sqldb/sqldb.go @@ -37,30 +37,13 @@ func (c *sqlDbClient) ConnectionString(ctx context.Context, subId, rgName, serve return "", err } - // Will delete this if not using: get list of databases for the server - // dbs := []armsql.Database{} - // pager := clientFactory.NewDatabasesClient().NewListByServerPager(rgName, serverName, &armsql.DatabasesClientListByServerOptions{SkipToken: nil}) - // for pager.More() { - // page, err := pager.NextPage(ctx) - // if err != nil { - // return "", fmt.Errorf("failed getting next page of databases: %w", err) - // } - - // for _, db := range page.DatabaseListResult.Value { - // if db != nil && db.Name != nil { - // dbs = append(dbs, *db) - // } - // } - - // } - // get server fully qualified domain name res, err := clientFactory.NewServersClient().Get(ctx, rgName, serverName, &armsql.ServersClientGetOptions{Expand: nil}) if err != nil { return "", fmt.Errorf("failed getting server '%s' for resource group '%s'", serverName, rgName) } - serverDomain := *res.Properties.FullyQualifiedDomainName + serverDomain := *res.Server.Properties.FullyQualifiedDomainName if serverDomain == "" { return "", fmt.Errorf("failed getting fully qualified domain name from server '%s'", serverName) diff --git a/cli/azd/resources/apphost/templates/resources.bicept b/cli/azd/resources/apphost/templates/resources.bicept index 14c180b5543..1dd239f7167 100644 --- a/cli/azd/resources/apphost/templates/resources.bicept +++ b/cli/azd/resources/apphost/templates/resources.bicept @@ -370,7 +370,7 @@ resource {{bicepName $name}}Firewall 'Microsoft.Sql/servers/firewallRules@2022-0 } {{range $cname := $value.Databases}} - resource {{bicepName $cname}} 'databases@2022-05-01-preview' = { + resource {{bicepName $cname}} 'Microsoft.Sql/servers/databases@2022-05-01-preview' = { name: '{{$cname}}' parent: {{bicepName $name}} location: location From 22b5a660a166498777e6fffd1243e86532641e8a Mon Sep 17 00:00:00 2001 From: hemarina Date: Thu, 25 Jan 2024 21:50:17 -0800 Subject: [PATCH 09/21] revert it --- cli/azd/pkg/apphost/generate.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cli/azd/pkg/apphost/generate.go b/cli/azd/pkg/apphost/generate.go index d2d7d6050c7..ba12f182be9 100644 --- a/cli/azd/pkg/apphost/generate.go +++ b/cli/azd/pkg/apphost/generate.go @@ -920,15 +920,12 @@ func (b infraGenerator) evalBindingRef(v string, emitType inputEmitType) (string default: return "", errUnsupportedProperty("azure.servicebus.v0", prop) } - case targetType == "azure.appinsights.v0" || - targetType == "azure.sql.database.v0" || - targetType == "sqlserver.database.v0" || - targetType == "sqlserver.database.v1": + case targetType == "azure.appinsights.v0": switch prop { case "connectionString": return fmt.Sprintf("{{ .Env.SERVICE_BINDING_%s_CONNECTION_STRING }}", scaffold.AlphaSnakeUpper(resource)), nil default: - return "", errUnsupportedProperty(targetType, prop) + return "", errUnsupportedProperty("azure.appinsights.v0", prop) } case targetType == "azure.cosmosdb.connection.v0" || targetType == "postgres.connection.v0" || From c289b0d89abab6b59c7fb5f00edc456f7bc8aac7 Mon Sep 17 00:00:00 2001 From: hemarina Date: Thu, 25 Jan 2024 22:01:29 -0800 Subject: [PATCH 10/21] debug --- cli/azd/pkg/project/service_target_dotnet_containerapp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/azd/pkg/project/service_target_dotnet_containerapp.go b/cli/azd/pkg/project/service_target_dotnet_containerapp.go index 9df7955d085..eec31587311 100644 --- a/cli/azd/pkg/project/service_target_dotnet_containerapp.go +++ b/cli/azd/pkg/project/service_target_dotnet_containerapp.go @@ -413,7 +413,7 @@ func (fns *containerAppTemplateManifestFuncs) ConnectionString(name string) (str case "azure.cosmosdb.database.v0": // get the parent resource name, which is the cosmos account name return fns.cosmosConnectionString(*resource.Parent) - case "azure.sql.account.v0", "sqlserver.account.v0": + case "azure.sql.v0", "sqlserver.server.v0", "sqlserver.server.v1": return fns.sqlConnectionString(name, "") case "azure.sql.database.v0", "sqlserver.database.v0", "sqlserver.database.v1": return fns.sqlConnectionString(*resource.Parent, name) From b0cdfa12b50087651239c88c48b54104388369f8 Mon Sep 17 00:00:00 2001 From: hemarina Date: Thu, 25 Jan 2024 22:05:22 -0800 Subject: [PATCH 11/21] lll --- cli/azd/pkg/sqldb/sqldb.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cli/azd/pkg/sqldb/sqldb.go b/cli/azd/pkg/sqldb/sqldb.go index f4c8d3f08c0..c4902da7613 100644 --- a/cli/azd/pkg/sqldb/sqldb.go +++ b/cli/azd/pkg/sqldb/sqldb.go @@ -31,7 +31,7 @@ func NewSqlDbService( } // ConnectionString returns the connection string for the CosmosDB account -func (c *sqlDbClient) ConnectionString(ctx context.Context, subId, rgName, serverName string, dbName string) (string, error) { +func (c *sqlDbClient) ConnectionString(ctx context.Context, subId, rgName, serverName, dbName string) (string, error) { clientFactory, err := armsql.NewClientFactory(subId, c.credential, c.options) if err != nil { return "", err @@ -51,8 +51,11 @@ func (c *sqlDbClient) ConnectionString(ctx context.Context, subId, rgName, serve // connection string for the server with no database if dbName == "" { - return fmt.Sprintf("Server=tcp:%s,1433;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;Authentication=\"Active Directory Default\";", serverDomain), nil + return fmt.Sprintf("Server=tcp:%s,1433;Encrypt=True;TrustServerCertificate=False;"+ + "Connection Timeout=30;Authentication=\"Active Directory Default\";", serverDomain), nil } - return fmt.Sprintf("Server=tcp:%s,1433;Encrypt=True;Initial Catalog=%s;TrustServerCertificate=False;Connection Timeout=30;Authentication=\"Active Directory Default\";", serverDomain, dbName), nil + return fmt.Sprintf("Server=tcp:%s,1433;Encrypt=True;Initial Catalog=%s;"+ + "TrustServerCertificate=False;Connection Timeout=30;Authentication=\"Active Directory Default\";", + serverDomain, dbName), nil } From dbd2120b32eaa7241135588fa3f4e3b441836894 Mon Sep 17 00:00:00 2001 From: hemarina Date: Thu, 25 Jan 2024 22:09:33 -0800 Subject: [PATCH 12/21] cspell --- cli/azd/.vscode/cspell-azd-dictionary.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/cli/azd/.vscode/cspell-azd-dictionary.txt b/cli/azd/.vscode/cspell-azd-dictionary.txt index 3194c77fe1a..18ff1812454 100644 --- a/cli/azd/.vscode/cspell-azd-dictionary.txt +++ b/cli/azd/.vscode/cspell-azd-dictionary.txt @@ -21,6 +21,7 @@ armappplatform armcognitiveservices armcosmos armresourcegraph +armsql asyncmy asyncpg azapi From e7f70223babc52a5ace7546530c0af437761cc67 Mon Sep 17 00:00:00 2001 From: hemarina Date: Thu, 25 Jan 2024 22:34:37 -0800 Subject: [PATCH 13/21] add server --- cli/azd/pkg/apphost/generate.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/azd/pkg/apphost/generate.go b/cli/azd/pkg/apphost/generate.go index ba12f182be9..1dffa4bacdd 100644 --- a/cli/azd/pkg/apphost/generate.go +++ b/cli/azd/pkg/apphost/generate.go @@ -903,6 +903,9 @@ func (b infraGenerator) evalBindingRef(v string, emitType inputEmitType) (string targetType == "redis.v0" || targetType == "azure.cosmosdb.account.v0" || targetType == "azure.cosmosdb.database.v0" || + targetType == "azure.sql.v0" || + targetType == "sqlserver.server.v0" || + targetType == "sqlserver.server.v1" || targetType == "azure.sql.database.v0" || targetType == "sqlserver.database.v0" || targetType == "sqlserver.database.v1": From 83f299ef53dfa07bd7c35a05e00778807fab78ab Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Fri, 26 Jan 2024 06:47:36 +0000 Subject: [PATCH 14/21] lint --- cli/azd/pkg/apphost/generate.go | 2 +- cli/azd/pkg/azd/default.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/azd/pkg/apphost/generate.go b/cli/azd/pkg/apphost/generate.go index 1dffa4bacdd..fa76a73482a 100644 --- a/cli/azd/pkg/apphost/generate.go +++ b/cli/azd/pkg/apphost/generate.go @@ -903,7 +903,7 @@ func (b infraGenerator) evalBindingRef(v string, emitType inputEmitType) (string targetType == "redis.v0" || targetType == "azure.cosmosdb.account.v0" || targetType == "azure.cosmosdb.database.v0" || - targetType == "azure.sql.v0" || + targetType == "azure.sql.v0" || targetType == "sqlserver.server.v0" || targetType == "sqlserver.server.v1" || targetType == "azure.sql.database.v0" || diff --git a/cli/azd/pkg/azd/default.go b/cli/azd/pkg/azd/default.go index b9e4058c4bf..17c9ebdbe0d 100644 --- a/cli/azd/pkg/azd/default.go +++ b/cli/azd/pkg/azd/default.go @@ -113,7 +113,7 @@ func (p *DefaultPlatform) ConfigureContainer(container *ioc.NestedContainer) err container.MustRegisterSingleton(cosmosdb.NewCosmosDbService) // sqldb - container.RegisterSingleton(sqldb.NewSqlDbService) + container.MustRegisterSingleton(sqldb.NewSqlDbService) // Templates From 4bb85571af5b4be2ddc264020a45490eb1e6c649 Mon Sep 17 00:00:00 2001 From: hemarina <104857065+hemarina@users.noreply.github.com> Date: Thu, 25 Jan 2024 22:52:17 -0800 Subject: [PATCH 15/21] Update cli/azd/pkg/project/service_target_dotnet_containerapp.go Co-authored-by: Victor Vazquez --- cli/azd/pkg/project/service_target_dotnet_containerapp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/azd/pkg/project/service_target_dotnet_containerapp.go b/cli/azd/pkg/project/service_target_dotnet_containerapp.go index eec31587311..048da56f201 100644 --- a/cli/azd/pkg/project/service_target_dotnet_containerapp.go +++ b/cli/azd/pkg/project/service_target_dotnet_containerapp.go @@ -438,7 +438,7 @@ func (fns *containerAppTemplateManifestFuncs) cosmosConnectionString(accountName resourceName) } -func (fns *containerAppTemplateManifestFuncs) sqlConnectionString(serverName string, sqlDbName string) (string, error) { +func (fns *containerAppTemplateManifestFuncs) sqlConnectionString(serverName, sqlDbName string) (string, error) { serverNameKey := fmt.Sprintf("SERVICE_BINDING_%s_NAME", scaffold.AlphaSnakeUpper(serverName)) resourceName := fns.env.Getenv(serverNameKey) if resourceName == "" { From 99dfc33673b6cd0d1c412de61619a772ed7763da Mon Sep 17 00:00:00 2001 From: hemarina Date: Fri, 26 Jan 2024 10:30:52 -0800 Subject: [PATCH 16/21] simple the code based on feedback and merge --- cli/azd/pkg/apphost/generate.go | 3 +++ cli/azd/pkg/azd/default.go | 2 +- .../project/service_target_dotnet_containerapp.go | 2 +- cli/azd/pkg/sqldb/sqldb.go | 13 ++++++------- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/cli/azd/pkg/apphost/generate.go b/cli/azd/pkg/apphost/generate.go index ba12f182be9..fa76a73482a 100644 --- a/cli/azd/pkg/apphost/generate.go +++ b/cli/azd/pkg/apphost/generate.go @@ -903,6 +903,9 @@ func (b infraGenerator) evalBindingRef(v string, emitType inputEmitType) (string targetType == "redis.v0" || targetType == "azure.cosmosdb.account.v0" || targetType == "azure.cosmosdb.database.v0" || + targetType == "azure.sql.v0" || + targetType == "sqlserver.server.v0" || + targetType == "sqlserver.server.v1" || targetType == "azure.sql.database.v0" || targetType == "sqlserver.database.v0" || targetType == "sqlserver.database.v1": diff --git a/cli/azd/pkg/azd/default.go b/cli/azd/pkg/azd/default.go index b9e4058c4bf..17c9ebdbe0d 100644 --- a/cli/azd/pkg/azd/default.go +++ b/cli/azd/pkg/azd/default.go @@ -113,7 +113,7 @@ func (p *DefaultPlatform) ConfigureContainer(container *ioc.NestedContainer) err container.MustRegisterSingleton(cosmosdb.NewCosmosDbService) // sqldb - container.RegisterSingleton(sqldb.NewSqlDbService) + container.MustRegisterSingleton(sqldb.NewSqlDbService) // Templates diff --git a/cli/azd/pkg/project/service_target_dotnet_containerapp.go b/cli/azd/pkg/project/service_target_dotnet_containerapp.go index eec31587311..048da56f201 100644 --- a/cli/azd/pkg/project/service_target_dotnet_containerapp.go +++ b/cli/azd/pkg/project/service_target_dotnet_containerapp.go @@ -438,7 +438,7 @@ func (fns *containerAppTemplateManifestFuncs) cosmosConnectionString(accountName resourceName) } -func (fns *containerAppTemplateManifestFuncs) sqlConnectionString(serverName string, sqlDbName string) (string, error) { +func (fns *containerAppTemplateManifestFuncs) sqlConnectionString(serverName, sqlDbName string) (string, error) { serverNameKey := fmt.Sprintf("SERVICE_BINDING_%s_NAME", scaffold.AlphaSnakeUpper(serverName)) resourceName := fns.env.Getenv(serverNameKey) if resourceName == "" { diff --git a/cli/azd/pkg/sqldb/sqldb.go b/cli/azd/pkg/sqldb/sqldb.go index c4902da7613..08fecc95bb6 100644 --- a/cli/azd/pkg/sqldb/sqldb.go +++ b/cli/azd/pkg/sqldb/sqldb.go @@ -49,13 +49,12 @@ func (c *sqlDbClient) ConnectionString(ctx context.Context, subId, rgName, serve return "", fmt.Errorf("failed getting fully qualified domain name from server '%s'", serverName) } - // connection string for the server with no database - if dbName == "" { - return fmt.Sprintf("Server=tcp:%s,1433;Encrypt=True;TrustServerCertificate=False;"+ - "Connection Timeout=30;Authentication=\"Active Directory Default\";", serverDomain), nil + var initialCatalog string + if dbName != "" { + initialCatalog = fmt.Sprintf("Initial Catalog=%s;", dbName) } - - return fmt.Sprintf("Server=tcp:%s,1433;Encrypt=True;Initial Catalog=%s;"+ + + return fmt.Sprintf("Server=tcp:%s,1433;Encrypt=True;%s"+ "TrustServerCertificate=False;Connection Timeout=30;Authentication=\"Active Directory Default\";", - serverDomain, dbName), nil + serverDomain, initialCatalog), nil } From 025cb3d4cce989b4502c12a4036048377952886a Mon Sep 17 00:00:00 2001 From: hemarina Date: Fri, 26 Jan 2024 10:35:14 -0800 Subject: [PATCH 17/21] remove v1 as bug fixed by aspire team --- cli/azd/pkg/apphost/generate.go | 8 +++----- cli/azd/pkg/project/service_target_dotnet_containerapp.go | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/cli/azd/pkg/apphost/generate.go b/cli/azd/pkg/apphost/generate.go index fa76a73482a..94cf4338d02 100644 --- a/cli/azd/pkg/apphost/generate.go +++ b/cli/azd/pkg/apphost/generate.go @@ -343,9 +343,9 @@ func (b *infraGenerator) LoadManifest(m *Manifest) error { b.addCosmosDbAccount(name) case "azure.cosmosdb.database.v0": b.addCosmosDatabase(*comp.Parent, name) - case "azure.sql.v0", "sqlserver.server.v0", "sqlserver.server.v1": + case "azure.sql.v0", "sqlserver.server.v0": b.addSqlServer(name) - case "azure.sql.database.v0", "sqlserver.database.v0", "sqlserver.database.v1": + case "azure.sql.database.v0", "sqlserver.database.v0": b.addSqlDatabase(*comp.Parent, name) case "postgres.server.v0": // We currently use a ACA Postgres Service per database. Because of this, we don't need to retain any @@ -905,10 +905,8 @@ func (b infraGenerator) evalBindingRef(v string, emitType inputEmitType) (string targetType == "azure.cosmosdb.database.v0" || targetType == "azure.sql.v0" || targetType == "sqlserver.server.v0" || - targetType == "sqlserver.server.v1" || targetType == "azure.sql.database.v0" || - targetType == "sqlserver.database.v0" || - targetType == "sqlserver.database.v1": + targetType == "sqlserver.database.v0": switch prop { case "connectionString": // returns something like {{ connectionString "resource" }} diff --git a/cli/azd/pkg/project/service_target_dotnet_containerapp.go b/cli/azd/pkg/project/service_target_dotnet_containerapp.go index 048da56f201..a881caf1268 100644 --- a/cli/azd/pkg/project/service_target_dotnet_containerapp.go +++ b/cli/azd/pkg/project/service_target_dotnet_containerapp.go @@ -413,9 +413,9 @@ func (fns *containerAppTemplateManifestFuncs) ConnectionString(name string) (str case "azure.cosmosdb.database.v0": // get the parent resource name, which is the cosmos account name return fns.cosmosConnectionString(*resource.Parent) - case "azure.sql.v0", "sqlserver.server.v0", "sqlserver.server.v1": + case "azure.sql.v0", "sqlserver.server.v0": return fns.sqlConnectionString(name, "") - case "azure.sql.database.v0", "sqlserver.database.v0", "sqlserver.database.v1": + case "azure.sql.database.v0", "sqlserver.database.v0": return fns.sqlConnectionString(*resource.Parent, name) default: return "", fmt.Errorf("connectionString: unsupported resource type '%s'", resource.Type) From dfbdf5e30186e8013e855e4afc55fc543000211f Mon Sep 17 00:00:00 2001 From: hemarina Date: Fri, 26 Jan 2024 12:09:22 -0800 Subject: [PATCH 18/21] run gofmt --- cli/azd/pkg/sqldb/sqldb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/azd/pkg/sqldb/sqldb.go b/cli/azd/pkg/sqldb/sqldb.go index 08fecc95bb6..39032baa035 100644 --- a/cli/azd/pkg/sqldb/sqldb.go +++ b/cli/azd/pkg/sqldb/sqldb.go @@ -53,7 +53,7 @@ func (c *sqlDbClient) ConnectionString(ctx context.Context, subId, rgName, serve if dbName != "" { initialCatalog = fmt.Sprintf("Initial Catalog=%s;", dbName) } - + return fmt.Sprintf("Server=tcp:%s,1433;Encrypt=True;%s"+ "TrustServerCertificate=False;Connection Timeout=30;Authentication=\"Active Directory Default\";", serverDomain, initialCatalog), nil From 70dfd879b522b884f1aa2293dba38f16752ecf29 Mon Sep 17 00:00:00 2001 From: hemarina Date: Mon, 29 Jan 2024 10:37:09 -0800 Subject: [PATCH 19/21] add error check for each case in pointer --- cli/azd/pkg/apphost/generate.go | 2 +- cli/azd/pkg/sqldb/sqldb.go | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cli/azd/pkg/apphost/generate.go b/cli/azd/pkg/apphost/generate.go index f2a72b11444..d11e1b3df76 100644 --- a/cli/azd/pkg/apphost/generate.go +++ b/cli/azd/pkg/apphost/generate.go @@ -899,8 +899,8 @@ func (b infraGenerator) evalBindingRef(v string, emitType inputEmitType) (string targetType == "azure.cosmosdb.account.v0" || targetType == "azure.cosmosdb.database.v0" || targetType == "azure.sql.v0" || - targetType == "sqlserver.server.v0" || targetType == "azure.sql.database.v0" || + targetType == "sqlserver.server.v0" || targetType == "sqlserver.database.v0": switch prop { case "connectionString": diff --git a/cli/azd/pkg/sqldb/sqldb.go b/cli/azd/pkg/sqldb/sqldb.go index 39032baa035..a76bdb076bd 100644 --- a/cli/azd/pkg/sqldb/sqldb.go +++ b/cli/azd/pkg/sqldb/sqldb.go @@ -43,9 +43,11 @@ func (c *sqlDbClient) ConnectionString(ctx context.Context, subId, rgName, serve return "", fmt.Errorf("failed getting server '%s' for resource group '%s'", serverName, rgName) } - serverDomain := *res.Server.Properties.FullyQualifiedDomainName + if res.Server.Properties == nil { + return "", fmt.Errorf("failed getting server properties from server '%s'", serverName) + } - if serverDomain == "" { + if res.Server.Properties.FullyQualifiedDomainName == nil { return "", fmt.Errorf("failed getting fully qualified domain name from server '%s'", serverName) } @@ -56,5 +58,5 @@ func (c *sqlDbClient) ConnectionString(ctx context.Context, subId, rgName, serve return fmt.Sprintf("Server=tcp:%s,1433;Encrypt=True;%s"+ "TrustServerCertificate=False;Connection Timeout=30;Authentication=\"Active Directory Default\";", - serverDomain, initialCatalog), nil + *res.Server.Properties.FullyQualifiedDomainName, initialCatalog), nil } From f81a4f19c51c4dedb23a285a1d46bd39184a40c2 Mon Sep 17 00:00:00 2001 From: hemarina Date: Mon, 29 Jan 2024 10:41:52 -0800 Subject: [PATCH 20/21] apply nested resources --- cli/azd/resources/apphost/templates/resources.bicept | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/cli/azd/resources/apphost/templates/resources.bicept b/cli/azd/resources/apphost/templates/resources.bicept index 1dd239f7167..b51db3b69bf 100644 --- a/cli/azd/resources/apphost/templates/resources.bicept +++ b/cli/azd/resources/apphost/templates/resources.bicept @@ -325,7 +325,6 @@ resource {{bicepName $name}} 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' ] databaseAccountOfferType: 'Standard' } -} {{range $cname := $value.Databases}} resource {{bicepName $cname}} 'sqlDatabases@2023-04-15' = { name: '{{$cname}}' @@ -338,7 +337,7 @@ resource {{bicepName $name}} 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' } } {{end -}} - +} {{end -}} {{range $name, $value := .SqlServers}} @@ -358,11 +357,9 @@ resource {{bicepName $name}} 'Microsoft.Sql/servers@2022-05-01-preview' = { tenantId: subscription().tenantId } } -} -resource {{bicepName $name}}Firewall 'Microsoft.Sql/servers/firewallRules@2022-05-01-preview' = { +resource {{bicepName $name}}Firewall 'firewallRules@2022-05-01-preview' = { name: 'fw-{{$name}}' - parent: {{bicepName $name}} properties: { startIpAddress: '0.0.0.0' endIpAddress: '255.255.255.255' @@ -370,9 +367,8 @@ resource {{bicepName $name}}Firewall 'Microsoft.Sql/servers/firewallRules@2022-0 } {{range $cname := $value.Databases}} - resource {{bicepName $cname}} 'Microsoft.Sql/servers/databases@2022-05-01-preview' = { + resource {{bicepName $cname}} 'databases@2022-05-01-preview' = { name: '{{$cname}}' - parent: {{bicepName $name}} location: location sku: { name: 'S0' @@ -380,6 +376,7 @@ resource {{bicepName $name}}Firewall 'Microsoft.Sql/servers/firewallRules@2022-0 tags: union(tags, {'aspire-resource-name': '{{$cname}}'}) } {{end -}} +} {{end -}} output MANAGED_IDENTITY_CLIENT_ID string = managedIdentity.properties.clientId {{if .HasContainerRegistry -}} From eed0f53adb88de9c778ed3be2d79746c291eebdc Mon Sep 17 00:00:00 2001 From: hemarina <104857065+hemarina@users.noreply.github.com> Date: Mon, 29 Jan 2024 16:45:28 -0800 Subject: [PATCH 21/21] Update cli/azd/pkg/sqldb/sqldb.go Co-authored-by: Wei Lim --- cli/azd/pkg/sqldb/sqldb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/azd/pkg/sqldb/sqldb.go b/cli/azd/pkg/sqldb/sqldb.go index a76bdb076bd..48d5e564aab 100644 --- a/cli/azd/pkg/sqldb/sqldb.go +++ b/cli/azd/pkg/sqldb/sqldb.go @@ -47,7 +47,7 @@ func (c *sqlDbClient) ConnectionString(ctx context.Context, subId, rgName, serve return "", fmt.Errorf("failed getting server properties from server '%s'", serverName) } - if res.Server.Properties.FullyQualifiedDomainName == nil { + if res.Server.Properties.FullyQualifiedDomainName == nil || len(*res.Server.Properties.FullyQualifiedDomainName) == 0 { return "", fmt.Errorf("failed getting fully qualified domain name from server '%s'", serverName) }