Skip to content

Commit

Permalink
add azure storage
Browse files Browse the repository at this point in the history
  • Loading branch information
saragluna committed Dec 20, 2024
1 parent ef05268 commit 8dbf2d4
Show file tree
Hide file tree
Showing 19 changed files with 1,267 additions and 121 deletions.
17 changes: 17 additions & 0 deletions cli/azd/internal/appdetect/appdetect.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ type Project struct {
// Experimental: Database dependencies inferred through heuristics while scanning dependencies in the project.
DatabaseDeps []DatabaseDep

// Experimental: Azure dependencies inferred through heuristics while scanning dependencies in the project.
AzureDeps []AzureDep

// The path to the project directory.
Path string

Expand All @@ -151,6 +154,20 @@ type Project struct {
Docker *Docker
}

//type AzureDep string

type AzureDep interface {
ResourceDisplay() string
}

type AzureDepStorageAccount struct {
ContainerNamePropertyMap map[string]string
}

func (a AzureDepStorageAccount) ResourceDisplay() string {
return "Azure Storage Account"
}

func (p *Project) HasWebUIFramework() bool {
for _, f := range p.Dependencies {
if f.IsWebUIFramework() {
Expand Down
29 changes: 29 additions & 0 deletions cli/azd/internal/auth_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package internal

// AuthType defines different authentication types.
type AuthType string

const (
AuthTypeUnspecified AuthType = "unspecified"
// Username and password, or key based authentication
AuthTypePassword AuthType = "password"
// Connection string authentication
AuthTypeConnectionString AuthType = "connectionString"
// Microsoft EntraID token credential
AuthTypeUserAssignedManagedIdentity AuthType = "userAssignedManagedIdentity"
)

func GetAuthTypeDescription(authType AuthType) string {
switch authType {
case AuthTypeUnspecified:
return "Unspecified"
case AuthTypePassword:
return "Username and password"
case AuthTypeConnectionString:
return "Connection string"
case AuthTypeUserAssignedManagedIdentity:
return "User assigned managed identity"
default:
return "Unspecified"
}
}
84 changes: 84 additions & 0 deletions cli/azd/internal/repository/app_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ var dbMap = map[appdetect.DatabaseDep]struct{}{

var featureCompose = alpha.MustFeatureKey("compose")

var azureDepMap = map[string]struct{}{
appdetect.AzureDepStorageAccount{}.ResourceDisplay(): {},
}

// InitFromApp initializes the infra directory and project file from the current existing app.
func (i *Initializer) InitFromApp(
ctx context.Context,
Expand Down Expand Up @@ -124,6 +128,18 @@ func (i *Initializer) InitFromApp(
if prj.Language == appdetect.DotNetAppHost {
prjAppHost = append(prjAppHost, prj)
}

if prj.Language == appdetect.Java {
for _, dep := range prj.AzureDeps {
if storageAccount, ok := dep.(appdetect.AzureDepStorageAccount); ok {
for property, containerName := range storageAccount.ContainerNamePropertyMap {
if containerName == "" {
promptMissingPropertyAndExit(i.console, ctx, property)
}
}
}
}
}
}

if len(prjAppHost) > 1 {
Expand Down Expand Up @@ -455,6 +471,28 @@ func (i *Initializer) prjConfigFromDetect(
dbNames[database] = db.Name
}

for _, azureDepPair := range detect.AzureDeps {
azureDep := azureDepPair.first
authType, err := chooseAuthTypeByPrompt(
azureDep.ResourceDisplay(),
[]internal.AuthType{internal.AuthTypeUserAssignedManagedIdentity, internal.AuthTypeConnectionString},
ctx,
i.console)
if err != nil {
return config, err
}
switch azureDep := azureDep.(type) {
case appdetect.AzureDepStorageAccount:
config.Resources["storage"] = &project.ResourceConfig{
Type: project.ResourceTypeStorage,
Props: project.StorageProps{
Containers: distinctValues(azureDep.ContainerNamePropertyMap),
AuthType: authType,
},
}
}
}

backends := []*project.ResourceConfig{}
frontends := []*project.ResourceConfig{}

Expand Down Expand Up @@ -483,6 +521,13 @@ func (i *Initializer) prjConfigFromDetect(
resSpec.Uses = append(resSpec.Uses, dbNames[db])
}

for _, azureDep := range svc.AzureDeps {
switch azureDep.(type) {
case appdetect.AzureDepStorageAccount:
resSpec.Uses = append(resSpec.Uses, "storage")
}
}

resSpec.Name = name
resSpec.Props = props
config.Resources[name] = &resSpec
Expand Down Expand Up @@ -578,3 +623,42 @@ func ServiceFromDetect(

return svc, nil
}

func chooseAuthTypeByPrompt(
name string,
authOptions []internal.AuthType,
ctx context.Context,
console input.Console) (internal.AuthType, error) {
var options []string
for _, option := range authOptions {
options = append(options, internal.GetAuthTypeDescription(option))
}
selection, err := console.Select(ctx, input.ConsoleOptions{
Message: "Choose auth type for " + name + ":",
Options: options,
})
if err != nil {
return internal.AuthTypeUnspecified, err
}
return authOptions[selection], nil
}

func promptMissingPropertyAndExit(console input.Console, ctx context.Context, key string) {
console.Message(ctx, fmt.Sprintf("No value was provided for %s. Please update the configuration file "+
"(like application.properties or application.yaml) with a valid value.", key))
os.Exit(0)
}

func distinctValues(input map[string]string) []string {
valueSet := make(map[string]struct{})
for _, value := range input {
valueSet[value] = struct{}{}
}

var result []string
for value := range valueSet {
result = append(result, value)
}

return result
}
12 changes: 12 additions & 0 deletions cli/azd/internal/repository/detect_confirm.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,17 @@ const (
EntryKindModified EntryKind = "modified"
)

type Pair struct {
first appdetect.AzureDep
second EntryKind
}

// detectConfirm handles prompting for confirming the detected services and databases
type detectConfirm struct {
// detected services and databases
Services []appdetect.Project
Databases map[appdetect.DatabaseDep]EntryKind
AzureDeps map[string]Pair

// the root directory of the project
root string
Expand All @@ -73,6 +79,12 @@ func (d *detectConfirm) Init(projects []appdetect.Project, root string) {
d.Databases[dbType] = EntryKindDetected
}
}

for _, azureDep := range project.AzureDeps {
if _, supported := azureDepMap[azureDep.ResourceDisplay()]; supported {
d.AzureDeps[azureDep.ResourceDisplay()] = Pair{azureDep, EntryKindDetected}
}
}
}

d.captureUsage(
Expand Down
23 changes: 14 additions & 9 deletions cli/azd/internal/repository/infra_confirm.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,24 @@ func (i *Initializer) infraSpecFromDetect(

switch db {
case appdetect.DbMongo:
serviceSpec.DbCosmosMongo = &scaffold.DatabaseReference{
DatabaseName: spec.DbCosmosMongo.DatabaseName,
}
err = scaffold.BindToMongoDb(&serviceSpec, spec.DbCosmosMongo)
case appdetect.DbPostgres:
serviceSpec.DbPostgres = &scaffold.DatabaseReference{
DatabaseName: spec.DbPostgres.DatabaseName,
}
err = scaffold.BindToPostgres(&serviceSpec, spec.DbPostgres)
case appdetect.DbRedis:
serviceSpec.DbRedis = &scaffold.DatabaseReference{
DatabaseName: "redis",
}
err = scaffold.BindToRedis(&serviceSpec, spec.DbRedis)
}
}

for _, azureDep := range svc.AzureDeps {
switch azureDep.(type) {
case appdetect.AzureDepStorageAccount:
err = scaffold.BindToStorageAccount(&serviceSpec, spec.AzureStorageAccount)
}
}

if err != nil {
return scaffold.InfraSpec{}, err
}
spec.Services = append(spec.Services, serviceSpec)
}

Expand Down
4 changes: 3 additions & 1 deletion cli/azd/internal/repository/infra_confirm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
)

func TestInitializer_infraSpecFromDetect(t *testing.T) {
envs, _ := scaffold.GetServiceBindingEnvsForPostgres()
tests := []struct {
name string
detect detectConfirm
Expand Down Expand Up @@ -183,9 +184,10 @@ func TestInitializer_infraSpecFromDetect(t *testing.T) {
},
},
},
DbPostgres: &scaffold.DatabaseReference{
DbPostgres: &scaffold.DatabasePostgres{
DatabaseName: "myappdb",
},
Envs: envs,
},
{
Name: "js",
Expand Down
Loading

0 comments on commit 8dbf2d4

Please sign in to comment.