Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
7466e88
Split spec_service_binding.go by app type: Spring Boot app, other app.
rujche Jan 14, 2025
b979bc4
Merge remote-tracking branch 'azure-javaee/feature/sjad' into split-s…
rujche Jan 14, 2025
ce86fed
Update cli/azd/internal/binding/binding_spring_boot.go
rujche Jan 14, 2025
6a95216
Fix test failure in infra_confirm_test.go.
rujche Jan 14, 2025
0ea4b48
Update the text of test.
rujche Jan 14, 2025
ad6cd7a
Fix error in bicep_env.go
rujche Jan 14, 2025
6e263c0
Fix error in bicep_env.go: "$service$name" -> "$service $name"
rujche Jan 14, 2025
636d1fa
Delete "type Env" because it's not used anymore.
rujche Jan 14, 2025
0376e59
In bicep_env_test.go, add test: "Eureka server" and "Config server". …
rujche Jan 14, 2025
bb5682d
Enhance test by renaming "configServerName" to "config-server-name"
rujche Jan 14, 2025
6f6e5d2
Fix GitHub action failure reported by lint.
rujche Jan 14, 2025
203cd4c
Skip test whose failure is not cause by current PR.
rujche Jan 14, 2025
8d1453a
Fix test failure: Test_ImportManager_ProjectInfrastructure_FromResources
rujche Jan 15, 2025
abe4b42
Delete "bindingEnvValuePrefix" because it's not used.
rujche Jan 15, 2025
c487900
Rename "EnvManagedIdentityClientId" to "SourceUserAssignedManagedIden…
rujche Jan 15, 2025
8905e23
Add unit test in TestIsBindingEnvValue, And fix test failure.
rujche Jan 15, 2025
8d880d4
Improve ToBicepEnv, and add unit test.
rujche Jan 15, 2025
79d5a0f
Change placeholder value to make it easier to understand.
rujche Jan 15, 2025
2a19da5
Create func: isPlaceholderOfSourceClientId
rujche Jan 15, 2025
19a6473
Fix error: UnmatchedPrincipalType: The PrincipalId 'xxx' has type 'Us…
rujche Jan 15, 2025
a601e70
Merge branch 'azure-javaee/feature/sjad' into split-spec_service_binding
rujche Jan 15, 2025
46e63cd
Remove duplicated codes in spec_service_binding.go by adding a new func.
rujche Jan 16, 2025
45a49a7
Use "map[MetadataType]string" to avoid contains spring boot related i…
rujche Jan 16, 2025
6fe9c3f
Merge branch 'azure-javaee/feature/sjad' into split-spec_service_binding
rujche Jan 20, 2025
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
2 changes: 1 addition & 1 deletion .github/workflows/go-test-for-sjad-branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ jobs:
- name: Run tests
run: |
cd ./cli/azd
go test $(go list ./... | grep -v github.com/azure/azure-dev/cli/azd/test/functional) -cover -v
go test $(go list ./... | grep -v github.com/azure/azure-dev/cli/azd/test/functional | grep -v github.com/azure/azure-dev/cli/azd/pkg/infra/provisioning/terraform) -cover -v

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore the test failure in current PR because it's not caused by current PR. The failure already exists in previous PR: #104

image

Maybe this failure can be fixed by merge upstream main, but I'm not sure. Anyway, skip related test in current PR.

147 changes: 147 additions & 0 deletions cli/azd/internal/binding/binding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package binding

import (
"fmt"
"strings"

"github.com/azure/azure-dev/cli/azd/internal"
)

func GetBindingEnvs(source Source, target Target) (map[string]string,
error) {
switch source.Type {
case Java, SpringBoot: // todo: support other Java types

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This todo will not be done in current PR.

return GetBindingEnvsForSpringBoot(source, target)
default:
return GetBindingEnvsForCommonSource(target)
}
}

type Source struct {
Type SourceType
Metadata map[MetadataType]string
}

type SourceType string
type MetadataType string

const (
Java SourceType = "java"
SpringBoot SourceType = "springBoot"
Unknown SourceType = "unknown"
)

type Target struct {
Type TargetType
Name string
AuthType internal.AuthType
}

type TargetType string

const (
AzureDatabaseForPostgresql TargetType = "azure.db.postgresql"
AzureDatabaseForMysql TargetType = "azure.db.mysql"
AzureCacheForRedis TargetType = "azure.db.redis"
AzureCosmosDBForMongoDB TargetType = "azure.db.cosmos.mongo"
AzureCosmosDBForNoSQL TargetType = "azure.db.cosmos.nosql"
AzureContainerApp TargetType = "azure.host.containerapp"
AzureOpenAiModel TargetType = "azure.ai.openai.model"
AzureServiceBus TargetType = "azure.messaging.servicebus"
AzureEventHubs TargetType = "azure.messaging.eventhubs"
AzureStorageAccount TargetType = "azure.storage"
)

type InfoType string

const (
InfoTypeHost InfoType = "host"
InfoTypePort InfoType = "port"
InfoTypeEndpoint InfoType = "endpoint"
InfoTypeDatabaseName InfoType = "databaseName"
InfoTypeNamespace InfoType = "namespace"
InfoTypeAccountName InfoType = "accountName"
InfoTypeUsername InfoType = "username"
InfoTypePassword InfoType = "password"
InfoTypeUrl InfoType = "url"
InfoTypeJdbcUrl InfoType = "jdbcUrl"
InfoTypeConnectionString InfoType = "connectionString"
InfoTypeSourceUserAssignedManagedIdentityClientId InfoType = "sourceUserAssignedManagedIdentityClientId"
)

const bindingEnvPrefix = "${binding:"
const bindingEnvSuffix = "}"
const bindingEnvFormat = bindingEnvPrefix + "%s:%s:%s" + bindingEnvSuffix
const SourceUserAssignedManagedIdentityClientId = bindingEnvPrefix +
"*:*:" + string(InfoTypeSourceUserAssignedManagedIdentityClientId) + bindingEnvSuffix

func IsBindingEnv(value string) bool {
_, infoType := ToTargetAndInfoType(value)
return infoType != ""
}

func ToBindingEnv(target Target, infoType InfoType) string {
return fmt.Sprintf(bindingEnvFormat, target.Type, target.Name, infoType)
}

func ReplaceBindingEnv(value string, substr string) string {
prefixIndex := strings.Index(value, bindingEnvPrefix)
if prefixIndex == -1 {
return value
}
suffixIndex := strings.Index(value, bindingEnvSuffix)
if suffixIndex == -1 {
return value
}
if prefixIndex >= suffixIndex {
return value
}
return value[0:prefixIndex] + substr + value[suffixIndex+1:]
}

func ToTargetAndInfoType(value string) (target Target, infoType InfoType) {
prefixIndex := strings.Index(value, bindingEnvPrefix)
if prefixIndex == -1 {
return Target{}, ""
}
suffixIndex := strings.Index(value, bindingEnvSuffix)
if suffixIndex == -1 {
return Target{}, ""
}
if prefixIndex >= suffixIndex {
return Target{}, ""
}
bindingEnv := value[prefixIndex:suffixIndex]
a := strings.Split(bindingEnv, ":")
if len(a) != 4 {
return Target{}, ""
}
targetTypeString := a[1]
targetNameString := a[2]
infoTypeString := a[3]
return Target{Type: TargetType(targetTypeString), Name: targetNameString}, InfoType(infoTypeString)
}

func MergeMapWithDuplicationCheck(a map[string]string, b map[string]string) (map[string]string, error) {
result := make(map[string]string)
for k, v := range a {
result[k] = v
}
for key, value := range b {
if existingValue, exist := result[key]; exist {
if value != existingValue {
return nil, duplicatedEnvError(existingValue, value)
}
} else {
result[key] = value
}
}
return result, nil
}

func duplicatedEnvError(existingValue string, newValue string) error {
return fmt.Errorf(
"duplicated environment variable. existingValue = %s, newValue = %s",
existingValue, newValue,
)
}
98 changes: 98 additions & 0 deletions cli/azd/internal/binding/binding_common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package binding

import (
"fmt"

"github.com/azure/azure-dev/cli/azd/internal"
)

func GetBindingEnvsForCommonSource(target Target) (map[string]string, error) {
switch target.Type {
case AzureDatabaseForPostgresql:
return GetBindingEnvsForCommonSourceToPostgresql(target.AuthType)
case AzureDatabaseForMysql:
return GetBindingEnvsForCommonSourceToMysql(target.AuthType)
case AzureCosmosDBForMongoDB:
return GetBindingEnvsForCommonSourceToMongoDB(target.AuthType)
case AzureCacheForRedis:
return GetBindingEnvsForCommonSourceToRedis(target.AuthType)
case AzureOpenAiModel:
return GetServiceBindingEnvsForAIModel(target.AuthType)
default:
return nil, fmt.Errorf("unsupported target type when binding for spring boot app, target.Type = %s",
target.Type)
}
}

func GetBindingEnvsForCommonSourceToPostgresql(authType internal.AuthType) (map[string]string, error) {
switch authType {
case internal.AuthTypePassword:
return map[string]string{
"POSTGRES_USERNAME": ToBindingEnv(Target{Type: AzureDatabaseForPostgresql}, InfoTypeUsername),
"POSTGRES_PASSWORD": ToBindingEnv(Target{Type: AzureDatabaseForPostgresql}, InfoTypePassword),
"POSTGRES_HOST": ToBindingEnv(Target{Type: AzureDatabaseForPostgresql}, InfoTypeHost),
"POSTGRES_DATABASE": ToBindingEnv(Target{Type: AzureDatabaseForPostgresql}, InfoTypeDatabaseName),
"POSTGRES_PORT": ToBindingEnv(Target{Type: AzureDatabaseForPostgresql}, InfoTypePort),
"POSTGRES_URL": ToBindingEnv(Target{Type: AzureDatabaseForPostgresql}, InfoTypeUrl),
}, nil
default:
return nil, unsupportedAuthTypeError(AzureDatabaseForPostgresql, authType)
}
}

func GetBindingEnvsForCommonSourceToMysql(authType internal.AuthType) (map[string]string, error) {
switch authType {
case internal.AuthTypePassword:
return map[string]string{
"MYSQL_USERNAME": ToBindingEnv(Target{Type: AzureDatabaseForMysql}, InfoTypeUsername),
"MYSQL_PASSWORD": ToBindingEnv(Target{Type: AzureDatabaseForMysql}, InfoTypePassword),
"MYSQL_HOST": ToBindingEnv(Target{Type: AzureDatabaseForMysql}, InfoTypeHost),
"MYSQL_DATABASE": ToBindingEnv(Target{Type: AzureDatabaseForMysql}, InfoTypeDatabaseName),
"MYSQL_PORT": ToBindingEnv(Target{Type: AzureDatabaseForMysql}, InfoTypePort),
"MYSQL_URL": ToBindingEnv(Target{Type: AzureDatabaseForMysql}, InfoTypeUrl),
}, nil
default:
return nil, unsupportedAuthTypeError(AzureDatabaseForMysql, authType)
}
}

func GetBindingEnvsForCommonSourceToMongoDB(authType internal.AuthType) (map[string]string, error) {
switch authType {
case internal.AuthTypeConnectionString:
return map[string]string{
"MONGODB_URL": ToBindingEnv(Target{Type: AzureCosmosDBForMongoDB}, InfoTypeUrl),
}, nil
default:
return nil, unsupportedAuthTypeError(AzureCosmosDBForMongoDB, authType)
}
}

func GetBindingEnvsForCommonSourceToRedis(authType internal.AuthType) (map[string]string, error) {
switch authType {
case internal.AuthTypePassword:
return map[string]string{
"REDIS_HOST": ToBindingEnv(Target{Type: AzureCacheForRedis}, InfoTypeHost),
"REDIS_PORT": ToBindingEnv(Target{Type: AzureCacheForRedis}, InfoTypePort),
"REDIS_ENDPOINT": ToBindingEnv(Target{Type: AzureCacheForRedis}, InfoTypeEndpoint),
"REDIS_URL": ToBindingEnv(Target{Type: AzureCacheForRedis}, InfoTypeUrl),
"REDIS_PASSWORD": ToBindingEnv(Target{Type: AzureCacheForRedis}, InfoTypePassword),
}, nil
default:
return nil, unsupportedAuthTypeError(AzureCacheForRedis, authType)
}
}

func GetServiceBindingEnvsForAIModel(authType internal.AuthType) (map[string]string, error) {
switch authType {
case internal.AuthTypeUserAssignedManagedIdentity:
return map[string]string{
"AZURE_OPENAI_ENDPOINT": ToBindingEnv(Target{Type: AzureOpenAiModel}, InfoTypeEndpoint),
}, nil
default:
return nil, unsupportedAuthTypeError(AzureOpenAiModel, authType)
}
}

func unsupportedAuthTypeError(targetType TargetType, authType internal.AuthType) error {
return fmt.Errorf("unsupported auth type, serviceType = %s, authType = %s", targetType, authType)
}
Loading