Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
57 changes: 57 additions & 0 deletions azuredevops/internal/service/core/data_project_features.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package core

import (
"context"
"fmt"
"time"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/client"
)

func DataProjectFeatures() *schema.Resource {
return &schema.Resource{
ReadContext: dataProjectFeaturesRead,
Timeouts: &schema.ResourceTimeout{
Read: schema.DefaultTimeout(5 * time.Minute),
},
Schema: map[string]*schema.Schema{
"project_id": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.IsUUID,
},
"features": {
Type: schema.TypeMap,
Computed: true,
},
},
}
}

func dataProjectFeaturesRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
clients := m.(*client.AggregatedClient)

projectID := d.Get("project_id").(string)
featureStates := d.Get("features").(map[string]interface{})
currentFeatureStates, err := getConfiguredProjectFeatureStates(ctx, clients.FeatureManagementClient, &featureStates, projectID)
if err != nil {
return diag.FromErr(err)
}
if currentFeatureStates == nil {
d.SetId("")
return diag.FromErr(fmt.Errorf("failed to retrieve current feature states for project: %s", projectID))
}

// Convert the upstream feature states to the expected map format
upstreamFeatures := make(map[string]interface{})
for featureType, enabledValue := range *currentFeatureStates {
upstreamFeatures[string(featureType)] = string(enabledValue)
}

d.SetId(projectID)
d.Set("features", upstreamFeatures)
return nil
}
15 changes: 5 additions & 10 deletions azuredevops/internal/service/core/resource_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7/core"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7/featuremanagement"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7/operations"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/client"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/utils"
Expand Down Expand Up @@ -86,6 +85,7 @@ func ResourceProject() *schema.Resource {
},
"features": {
Type: schema.TypeMap,
Computed: true,
Optional: true,
ValidateFunc: validateProjectFeatures,
Elem: &schema.Schema{
Expand Down Expand Up @@ -473,15 +473,10 @@ func flattenProject(clients *client.AggregatedClient, d *schema.ResourceData, pr
}
}

var currentFeatureStates *map[ProjectFeatureType]featuremanagement.ContributedFeatureEnabledValue
features, ok := d.GetOk("features")
if ok {
featureStates := features.(map[string]interface{})
states, err := getConfiguredProjectFeatureStates(clients.Ctx, clients.FeatureManagementClient, &featureStates, project.Id.String())
if err != nil {
return err
}
currentFeatureStates = states
featureStates := d.Get("features").(map[string]interface{})
currentFeatureStates, err := getConfiguredProjectFeatureStates(clients.Ctx, clients.FeatureManagementClient, &featureStates, project.Id.String())
if err != nil {
return err
}

d.Set("name", project.Name)
Expand Down
18 changes: 9 additions & 9 deletions azuredevops/internal/service/core/resource_project_features.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,14 @@
d.SetId("")
return diag.FromErr(fmt.Errorf("failed to retrieve current feature states for project: %s", projectID))
}
d.Set("features", currentFeatureStates)

// Convert the upstream feature states to the expected map format
upstreamFeatures := make(map[string]interface{})
for featureType, enabledValue := range *currentFeatureStates {
upstreamFeatures[string(featureType)] = string(enabledValue)
}

d.Set("features", upstreamFeatures)
return nil
}

Expand All @@ -135,21 +142,14 @@
return nil
}

func getConfiguredProjectFeatureStates(ctx context.Context, fc featuremanagement.Client, featureStates *map[string]interface{}, projectID string) (*map[ProjectFeatureType]featuremanagement.ContributedFeatureEnabledValue, error) {

Check failure on line 145 in azuredevops/internal/service/core/resource_project_features.go

View workflow job for this annotation

GitHub Actions / go-lint

`getConfiguredProjectFeatureStates` - `featureStates` is unused (unparam)
if featureStates == nil {
return nil, nil
}

Check failure on line 146 in azuredevops/internal/service/core/resource_project_features.go

View workflow job for this annotation

GitHub Actions / go-lint

File is not properly formatted (gofumpt)
currentFeatureStates, err := getProjectFeatureStates(ctx, fc, projectID)
if err != nil {
return nil, err
}

for k := range *currentFeatureStates {
if _, ok := (*featureStates)[string(k)]; !ok {
delete(*currentFeatureStates, k)
}
}
// Return all features as they exist upstream, without filtering
return currentFeatureStates, nil
}

Expand Down
1 change: 1 addition & 0 deletions azuredevops/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ func Provider() *schema.Provider {
"azuredevops_iteration": workitemtracking.DataIteration(),
"azuredevops_project": core.DataProject(),
"azuredevops_projects": core.DataProjects(),
"azuredevops_project_features": core.DataProjectFeatures(),
"azuredevops_securityrole_definitions": securityroles.DataSecurityRoleDefinitions(),
"azuredevops_serviceendpoint_azurecr": serviceendpoint.DataResourceServiceEndpointAzureCR(),
"azuredevops_serviceendpoint_azurerm": serviceendpoint.DataServiceEndpointAzureRM(),
Expand Down
2 changes: 2 additions & 0 deletions website/docs/d/project.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ The following attributes are exported:

* `process_template_id` - The process template ID for the project.

* `features` - The features for projects.

## Relevant Links

- [Azure DevOps Service REST API 7.0 - Projects - Get](https://docs.microsoft.com/en-us/rest/api/azure/devops/core/projects/get?view=azure-devops-rest-7.0)
Expand Down
54 changes: 54 additions & 0 deletions website/docs/d/project_features.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
layout: "azuredevops"
page_title: "AzureDevops: azuredevops_project_features"
description: |-
Use this data source to access information about the features of an existing Project within Azure DevOps.
---

# Data Source: azuredevops_project

Use this data source to access information about the features of an existing Project within Azure DevOps.

## Example Usage

```hcl
data "azuredevops_project" "example" {
name = "Example Project"
}

data "azuredevops_project_features" "example" {
project_id = data.azuredevops_project.example.id
}

output "project" {
value = data.azuredevops_project_features.features
}
```

## Argument Reference

The following arguments are supported:

* `project_id` - (Required) ID of the Project.

## Attributes Reference

The following attributes are exported:

* `project_id` - The ID of the project.

* `features` - The features for projects.

## Relevant Links

- [Azure DevOps Service REST API 7.1 - Queries - Get](https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/queries/get?view=azure-devops-rest-7.1&tabs=HTTP)

## Timeouts

The `timeouts` block allows you to specify [timeouts](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts) for certain actions:

* `read` - (Defaults to 5 minute) Used when retrieving the Project.

## PAT Permissions Required

- **Project & Team**: Read
Loading