func()

in cli/azd/pkg/project/dotnet_importer.go [200:369]


func (ai *DotNetImporter) Services(
	ctx context.Context, p *ProjectConfig, svcConfig *ServiceConfig,
) (map[string]*ServiceConfig, error) {
	services := make(map[string]*ServiceConfig)

	manifest, err := ai.ReadManifest(ctx, svcConfig)
	if err != nil {
		return nil, fmt.Errorf("generating app host manifest: %w", err)
	}

	projects := apphost.ProjectPaths(manifest)
	for name, path := range projects {
		relPath, err := filepath.Rel(p.Path, path)
		if err != nil {
			return nil, err
		}

		// TODO(ellismg): Some of this code is duplicated from project.Parse, we should centralize this logic long term.
		svc := &ServiceConfig{
			RelativePath: relPath,
			Language:     ServiceLanguageDotNet,
			Host:         DotNetContainerAppTarget,
		}

		svc.Name = name
		svc.Project = p
		svc.EventDispatcher = ext.NewEventDispatcher[ServiceLifecycleEventArgs]()

		svc.Infra.Provider, err = provisioning.ParseProvider(svc.Infra.Provider)
		if err != nil {
			return nil, fmt.Errorf("parsing service %s: %w", svc.Name, err)
		}

		svc.DotNetContainerApp = &DotNetContainerAppOptions{
			Manifest:    manifest,
			ProjectName: name,
			AppHostPath: svcConfig.Path(),
		}

		services[svc.Name] = svc
	}

	dockerfiles := apphost.Dockerfiles(manifest)
	for name, dockerfile := range dockerfiles {
		relPath, err := filepath.Rel(p.Path, filepath.Dir(dockerfile.Path))
		if err != nil {
			return nil, err
		}

		// TODO(ellismg): Some of this code is duplicated from project.Parse, we should centralize this logic long term.
		svc := &ServiceConfig{
			RelativePath: relPath,
			Language:     ServiceLanguageDocker,
			Host:         DotNetContainerAppTarget,
			Docker: DockerProjectOptions{
				Path:      dockerfile.Path,
				Context:   dockerfile.Context,
				BuildArgs: mapToExpandableStringSlice(dockerfile.BuildArgs, "="),
			},
		}

		svc.Name = name
		svc.Project = p
		svc.EventDispatcher = ext.NewEventDispatcher[ServiceLifecycleEventArgs]()

		svc.Infra.Provider, err = provisioning.ParseProvider(svc.Infra.Provider)
		if err != nil {
			return nil, fmt.Errorf("parsing service %s: %w", svc.Name, err)
		}

		svc.DotNetContainerApp = &DotNetContainerAppOptions{
			Manifest:    manifest,
			ProjectName: name,
			AppHostPath: svcConfig.Path(),
		}

		services[svc.Name] = svc
	}

	containers := apphost.Containers(manifest)
	for name, container := range containers {
		// TODO(ellismg): Some of this code is duplicated from project.Parse, we should centralize this logic long term.
		svc := &ServiceConfig{
			RelativePath: svcConfig.RelativePath,
			Language:     ServiceLanguageDotNet,
			Host:         DotNetContainerAppTarget,
		}

		svc.Name = name
		svc.Project = p
		svc.EventDispatcher = ext.NewEventDispatcher[ServiceLifecycleEventArgs]()

		svc.Infra.Provider, err = provisioning.ParseProvider(svc.Infra.Provider)
		if err != nil {
			return nil, fmt.Errorf("parsing service %s: %w", svc.Name, err)
		}

		svc.DotNetContainerApp = &DotNetContainerAppOptions{
			ContainerImage: container.Image,
			Manifest:       manifest,
			ProjectName:    name,
			AppHostPath:    svcConfig.Path(),
		}

		services[svc.Name] = svc
	}

	buildContainers, err := apphost.BuildContainers(manifest)
	if err != nil {
		return nil, err
	}
	for name, bContainer := range buildContainers {

		defaultLanguage := ServiceLanguageDotNet
		relativePath := svcConfig.RelativePath
		var dOptions DockerProjectOptions

		if bContainer.Build != nil {
			defaultLanguage = ServiceLanguageDocker
			relPath, err := filepath.Rel(p.Path, filepath.Dir(bContainer.Build.Dockerfile))
			if err != nil {
				return nil, err
			}
			relativePath = relPath

			bArgs, err := evaluateArgsWithConfig(*manifest, bContainer.Build.Args)
			if err != nil {
				return nil, fmt.Errorf("evaluating build args for service %s: %w", name, err)
			}
			bArgsArray, reqEnv, err := buildArgsArrayAndEnv(*manifest, bContainer.Build.Secrets)
			if err != nil {
				return nil, fmt.Errorf("converting build args to array for service %s: %w", name, err)
			}

			dOptions = DockerProjectOptions{
				Path:         bContainer.Build.Dockerfile,
				Context:      bContainer.Build.Context,
				BuildArgs:    mapToExpandableStringSlice(bArgs, "="),
				BuildSecrets: bArgsArray,
				BuildEnv:     reqEnv,
			}
		}

		svc := &ServiceConfig{
			RelativePath: relativePath,
			Language:     defaultLanguage,
			Host:         DotNetContainerAppTarget,
			Docker:       dOptions,
		}

		svc.Name = name
		svc.Project = p
		svc.EventDispatcher = ext.NewEventDispatcher[ServiceLifecycleEventArgs]()

		svc.Infra.Provider, err = provisioning.ParseProvider(svc.Infra.Provider)
		if err != nil {
			return nil, fmt.Errorf("parsing service %s: %w", svc.Name, err)
		}

		svc.DotNetContainerApp = &DotNetContainerAppOptions{
			ContainerImage: bContainer.Image,
			Manifest:       manifest,
			ProjectName:    name,
			AppHostPath:    svcConfig.Path(),
		}
		services[svc.Name] = svc

	}
	return services, nil
}