func()

in cli/azd/pkg/prompt/prompt_service.go [392:531]


func (ps *promptService) PromptSubscriptionResource(
	ctx context.Context,
	azureContext *AzureContext,
	options ResourceOptions,
) (*azapi.ResourceExtended, error) {
	if azureContext == nil {
		azureContext = NewEmptyAzureContext()
	}

	if err := azureContext.EnsureSubscription(ctx); err != nil {
		return nil, err
	}

	mergedSelectorOptions := &SelectOptions{}

	if options.SelectorOptions == nil {
		options.SelectorOptions = &SelectOptions{}
	}

	var existingResource *arm.ResourceID
	var resourceType string
	if options.ResourceType != nil {
		resourceType = string(*options.ResourceType)
		match, has := azureContext.Resources.FindByTypeAndKind(ctx, *options.ResourceType, options.Kinds)
		if has {
			existingResource = match
		}
	}

	if options.Selected == nil {
		options.Selected = func(resource *azapi.ResourceExtended) bool {
			if existingResource == nil {
				return false
			}

			if strings.EqualFold(resource.Id, existingResource.String()) {
				return true
			}

			return false
		}
	}

	resourceName := options.ResourceTypeDisplayName

	if resourceName == "" && options.ResourceType != nil {
		resourceName = string(*options.ResourceType)
	}

	if resourceName == "" {
		resourceName = "resource"
	}

	defaultSelectorOptions := &SelectOptions{
		Message:            fmt.Sprintf("Select %s", resourceName),
		LoadingMessage:     fmt.Sprintf("Loading %s resources...", resourceName),
		HelpMessage:        fmt.Sprintf("Choose an Azure %s for your project.", resourceName),
		AllowNewResource:   ux.Ptr(true),
		NewResourceMessage: fmt.Sprintf("Create new %s", resourceName),
	}

	if err := mergo.Merge(mergedSelectorOptions, options.SelectorOptions, mergo.WithoutDereference); err != nil {
		return nil, err
	}

	if err := mergo.Merge(mergedSelectorOptions, defaultSelectorOptions, mergo.WithoutDereference); err != nil {
		return nil, err
	}

	allowNewResource := mergedSelectorOptions.AllowNewResource != nil && *mergedSelectorOptions.AllowNewResource

	resource, err := PromptCustomResource(ctx, CustomResourceOptions[azapi.ResourceExtended]{
		NewResourceValue: azapi.ResourceExtended{
			Resource: azapi.Resource{
				Id:   "new",
				Type: resourceType,
			},
		},
		SelectorOptions: mergedSelectorOptions,
		LoadData: func(ctx context.Context) ([]*azapi.ResourceExtended, error) {
			var resourceListOptions *armresources.ClientListOptions
			if options.ResourceType != nil {
				resourceListOptions = &armresources.ClientListOptions{
					Filter: to.Ptr(fmt.Sprintf("resourceType eq '%s'", string(*options.ResourceType))),
				}
			}

			resourceList, err := ps.resourceService.ListSubscriptionResources(
				ctx,
				azureContext.Scope.SubscriptionId,
				resourceListOptions,
			)
			if err != nil {
				return nil, err
			}

			filteredResources := []*azapi.ResourceExtended{}
			hasKindFilter := len(options.Kinds) > 0

			for _, resource := range resourceList {
				if !hasKindFilter || slices.Contains(options.Kinds, resource.Kind) {
					filteredResources = append(filteredResources, resource)
				}
			}

			if len(filteredResources) == 0 && !allowNewResource {
				if options.ResourceType == nil {
					return nil, ErrNoResourcesFound
				}

				return nil, fmt.Errorf("no resources found with type '%v'", *options.ResourceType)
			}

			return filteredResources, nil
		},
		DisplayResource: func(resource *azapi.ResourceExtended) (string, error) {
			parsedResource, err := arm.ParseResourceID(resource.Id)
			if err != nil {
				return "", fmt.Errorf("parsing resource id: %w", err)
			}

			return fmt.Sprintf(
				"%s %s",
				parsedResource.Name,
				output.WithGrayFormat("(%s)", parsedResource.ResourceGroupName),
			), nil
		},
		Selected: options.Selected,
	})

	if err != nil {
		return nil, err
	}

	if err := azureContext.Resources.Add(resource.Id); err != nil {
		return nil, err
	}

	return resource, nil
}