in cli/azd/pkg/project/dotnet_importer.go [465:597]
func (ai *DotNetImporter) SynthAllInfrastructure(ctx context.Context, p *ProjectConfig, svcConfig *ServiceConfig,
) (fs.FS, error) {
manifest, err := ai.ReadManifest(ctx, svcConfig)
if err != nil {
return nil, fmt.Errorf("generating apphost manifest: %w", err)
}
generatedFS := memfs.New()
rootModuleName := DefaultModule
if p.Infra.Module != "" {
rootModuleName = p.Infra.Module
}
azdOperationsEnabled := ai.alphaFeatureManager.IsEnabled(provisioning.AzdOperationsFeatureKey)
infraFS, err := apphost.BicepTemplate(rootModuleName, manifest, apphost.AppHostOptions{
AzdOperations: azdOperationsEnabled,
})
if err != nil {
if errors.Is(err, provisioning.ErrAzdOperationsNotEnabled) {
// Use a warning for this error about azd operations is required for the current project to fully work
ai.console.Message(ctx, err.Error())
} else {
return nil, fmt.Errorf("generating infra/ folder: %w", err)
}
}
infraPathPrefix := DefaultPath
if p.Infra.Path != "" {
infraPathPrefix = p.Infra.Path
}
err = fs.WalkDir(infraFS, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
return nil
}
err = generatedFS.MkdirAll(filepath.Join(infraPathPrefix, filepath.Dir(path)), osutil.PermissionDirectoryOwnerOnly)
if err != nil {
return err
}
contents, err := fs.ReadFile(infraFS, path)
if err != nil {
return err
}
return generatedFS.WriteFile(filepath.Join(infraPathPrefix, path), contents, d.Type().Perm())
})
if err != nil {
return nil, err
}
// Use canonical paths for Rel comparison due to absolute paths provided by ManifestFromAppHost
// being possibly symlinked paths.
root, err := filepath.EvalSymlinks(p.Path)
if err != nil {
return nil, err
}
// writeManifestForResource writes the containerApp.tmpl.yaml or containerApp.bicepparam for the given resource to the
// generated filesystem. The manifest is written to a file name "containerApp.tmpl.yaml" or
// "containerApp.tmpl.bicepparam" in the same directory as the project that produces the
// container we will deploy.
writeManifestForResource := func(name string) error {
normalPath, err := filepath.EvalSymlinks(svcConfig.Path())
if err != nil {
return err
}
projectRelPath, err := filepath.Rel(root, normalPath)
if err != nil {
return err
}
containerAppManifest, manifestType, err := apphost.ContainerAppManifestTemplateForProject(
manifest, name, apphost.AppHostOptions{})
if err != nil {
return fmt.Errorf("generating containerApp deployment manifest for resource %s: %w", name, err)
}
manifestPath := filepath.Join(filepath.Dir(projectRelPath), "infra", fmt.Sprintf("%s.tmpl.yaml", name))
if manifestType == apphost.ContainerAppManifestTypeBicep {
manifestPath = filepath.Join(
filepath.Dir(projectRelPath), "infra", name, fmt.Sprintf("%s.tmpl.bicepparam", name))
}
if err := generatedFS.MkdirAll(filepath.Dir(manifestPath), osutil.PermissionDirectoryOwnerOnly); err != nil {
return err
}
err = generatedFS.WriteFile(manifestPath, []byte(containerAppManifest), osutil.PermissionFileOwnerOnly)
if err != nil {
return err
}
return nil
}
for name := range apphost.ProjectPaths(manifest) {
if err := writeManifestForResource(name); err != nil {
return nil, err
}
}
for name := range apphost.Dockerfiles(manifest) {
if err := writeManifestForResource(name); err != nil {
return nil, err
}
}
for name := range apphost.Containers(manifest) {
if err := writeManifestForResource(name); err != nil {
return nil, err
}
}
bcs, err := apphost.BuildContainers(manifest)
if err != nil {
return nil, err
}
for name := range bcs {
if err := writeManifestForResource(name); err != nil {
return nil, err
}
}
return generatedFS, nil
}