summaryrefslogtreecommitdiff
path: root/azuredevops
diff options
context:
space:
mode:
authorArnon S <arnon.san@cpf.co.th>2022-11-05 23:56:16 +0700
committerArnon S <arnon.san@cpf.co.th>2022-11-05 23:56:16 +0700
commit332c82b84685abca54d83b5f23adeea7bbbbef84 (patch)
tree0fff5571e71d0c7c7195236922590d46791e6c51 /azuredevops
parent270599b9a42e85380a0ac0e48ab164be922238fc (diff)
feat(serviceendpoint_externaltfs): initialized externaltfs service endpoint resource, tests, and docs
Diffstat (limited to 'azuredevops')
-rw-r--r--azuredevops/internal/acceptancetests/resource_serviceendpoint_externaltfs_test.go148
-rw-r--r--azuredevops/internal/service/serviceendpoint/resource_serviceendpoint_externaltfs.go111
-rw-r--r--azuredevops/internal/service/serviceendpoint/resource_serviceendpoint_externaltfs_test.go192
-rw-r--r--azuredevops/provider.go1
-rw-r--r--azuredevops/provider_test.go1
5 files changed, 453 insertions, 0 deletions
diff --git a/azuredevops/internal/acceptancetests/resource_serviceendpoint_externaltfs_test.go b/azuredevops/internal/acceptancetests/resource_serviceendpoint_externaltfs_test.go
new file mode 100644
index 00000000..6ee6f16a
--- /dev/null
+++ b/azuredevops/internal/acceptancetests/resource_serviceendpoint_externaltfs_test.go
@@ -0,0 +1,148 @@
+//go:build (all || resource_serviceendpoint_externaltfs) && !exclude_serviceendpoints
+// +build all resource_serviceendpoint_externaltfs
+// +build !exclude_serviceendpoints
+
+package acceptancetests
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+ "github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/acceptancetests/testutils"
+)
+
+func TestAccServiceEndpointExternalTFS_PersonalTokenBasic(t *testing.T) {
+ projectName := testutils.GenerateResourceName()
+ serviceEndpointName := testutils.GenerateResourceName()
+ resourceType := "azuredevops_serviceendpoint_externaltfs"
+ tfSvcEpNode := resourceType + ".serviceendpoint"
+ resource.ParallelTest(t, resource.TestCase{
+ PreCheck: func() { testutils.PreCheck(t, nil) },
+ Providers: testutils.GetProviders(),
+ CheckDestroy: testutils.CheckServiceEndpointDestroyed(resourceType),
+ Steps: []resource.TestStep{
+ {
+ Config: hclSvcEndpointExternalTFSResourceBasic(projectName, serviceEndpointName),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttrSet(tfSvcEpNode, "project_id"),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "auth_personal.#", "1"),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointName),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "description", "Managed by Terraform"),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "connection_url", "https://dev.azure.com/myorganization"),
+ testutils.CheckServiceEndpointExistsWithName(tfSvcEpNode, serviceEndpointName),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccServiceEndpointExternalTFS_PersonalTokenUpdate(t *testing.T) {
+ projectName := testutils.GenerateResourceName()
+ serviceEndpointNameFirst := testutils.GenerateResourceName()
+ serviceEndpointNameSecond := testutils.GenerateResourceName()
+ description := "Managed by Terraform"
+ resourceType := "azuredevops_serviceendpoint_externaltfs"
+ tfSvcEpNode := resourceType + ".serviceendpoint"
+ resource.ParallelTest(t, resource.TestCase{
+ PreCheck: func() { testutils.PreCheck(t, nil) },
+ Providers: testutils.GetProviders(),
+ CheckDestroy: testutils.CheckServiceEndpointDestroyed(resourceType),
+ Steps: []resource.TestStep{
+ {
+ Config: hclSvcEndpointExternalTFSResourceBasic(projectName, serviceEndpointNameFirst),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttrSet(tfSvcEpNode, "project_id"),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "auth_personal.#", "1"),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointNameFirst),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "connection_url", "https://dev.azure.com/myorganization"),
+ testutils.CheckServiceEndpointExistsWithName(tfSvcEpNode, serviceEndpointNameFirst),
+ ),
+ },
+ {
+ Config: hclSvcEndpointExternalTFSResourceUpdate(projectName, serviceEndpointNameSecond, description),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttrSet(tfSvcEpNode, "project_id"),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "auth_personal.#", "1"),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointNameSecond),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "description", description),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "connection_url", "https://dev.azure.com/myorganization"),
+ testutils.CheckServiceEndpointExistsWithName(tfSvcEpNode, serviceEndpointNameSecond),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccServiceEndpointExternalTFS_CreateAndUpdate(t *testing.T) {
+ projectName := testutils.GenerateResourceName()
+ serviceEndpointNameFirst := testutils.GenerateResourceName()
+ serviceEndpointNameSecond := testutils.GenerateResourceName()
+ resourceType := "azuredevops_serviceendpoint_externaltfs"
+ tfSvcEpNode := resourceType + ".serviceendpoint"
+ resource.ParallelTest(t, resource.TestCase{
+ PreCheck: func() { testutils.PreCheck(t, nil) },
+ Providers: testutils.GetProviders(),
+ CheckDestroy: testutils.CheckServiceEndpointDestroyed(resourceType),
+ Steps: []resource.TestStep{
+ {
+ Config: hclSvcEndpointExternalTFSResourceBasic(projectName, serviceEndpointNameFirst),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttrSet(tfSvcEpNode, "project_id"),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "auth_personal.#", "1"),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointNameFirst),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "description", "Managed by Terraform"),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "connection_url", "https://dev.azure.com/myorganization"),
+ testutils.CheckServiceEndpointExistsWithName(tfSvcEpNode, serviceEndpointNameFirst),
+ ),
+ },
+ {
+ Config: hclSvcEndpointExternalTFSResourceBasic(projectName, serviceEndpointNameSecond),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttrSet(tfSvcEpNode, "project_id"),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "auth_personal.#", "1"),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "service_endpoint_name", serviceEndpointNameSecond),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "description", "Managed by Terraform"),
+ resource.TestCheckResourceAttr(tfSvcEpNode, "connection_url", "https://dev.azure.com/myorganization"),
+ testutils.CheckServiceEndpointExistsWithName(tfSvcEpNode, serviceEndpointNameSecond),
+ ),
+ },
+ {
+ ResourceName: tfSvcEpNode,
+ ImportStateIdFunc: testutils.ComputeProjectQualifiedResourceImportID(tfSvcEpNode),
+ ImportState: true,
+ ImportStateVerify: true,
+ ImportStateVerifyIgnore: []string{"auth_personal"},
+ },
+ },
+ })
+}
+
+func hclSvcEndpointExternalTFSResourceBasic(projectName string, serviceEndpointName string) string {
+ projectResource := testutils.HclProjectResource(projectName)
+ serviceEndpointResource := fmt.Sprintf(`
+resource "azuredevops_serviceendpoint_externaltfs" "serviceendpoint" {
+ project_id = azuredevops_project.project.id
+ service_endpoint_name = "%[1]s"
+ connection_url = "https://dev.azure.com/myorganization"
+ auth_personal {
+ personal_access_token = "test_token_basic"
+ }
+}`, serviceEndpointName)
+ return fmt.Sprintf("%s\n%s", projectResource, serviceEndpointResource)
+}
+
+func hclSvcEndpointExternalTFSResourceUpdate(projectName string, serviceEndpointName string, description string) string {
+ projectResource := testutils.HclProjectResource(projectName)
+ serviceEndpointResource := fmt.Sprintf(`
+resource "azuredevops_serviceendpoint_externaltfs" "serviceendpoint" {
+ project_id = azuredevops_project.project.id
+ service_endpoint_name = "%[1]s"
+ connection_url = "https://dev.azure.com/myorganization"
+ auth_personal {
+ personal_access_token = "test_token_update"
+ }
+ description = "%[2]s"
+}`, serviceEndpointName, description)
+ return fmt.Sprintf("%s\n%s", projectResource, serviceEndpointResource)
+}
diff --git a/azuredevops/internal/service/serviceendpoint/resource_serviceendpoint_externaltfs.go b/azuredevops/internal/service/serviceendpoint/resource_serviceendpoint_externaltfs.go
new file mode 100644
index 00000000..9e97e39c
--- /dev/null
+++ b/azuredevops/internal/service/serviceendpoint/resource_serviceendpoint_externaltfs.go
@@ -0,0 +1,111 @@
+package serviceendpoint
+
+import (
+ "strings"
+
+ "github.com/google/uuid"
+ "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/v6/serviceendpoint"
+ "github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/utils/converter"
+ "github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/utils/tfhelper"
+)
+
+const (
+ personalAccessTokenExternalTFS = "personal_access_token"
+)
+
+func ResourceServiceEndpointExternalTFS() *schema.Resource {
+ r := genBaseServiceEndpointResource(flattenServiceEndpointExternalTFS, expandServiceEndpointExternalTFS)
+ r.Schema["connection_url"] = &schema.Schema{
+ Type: schema.TypeString,
+ ValidateFunc: validation.IsURLWithHTTPorHTTPS,
+ Required: true,
+ Description: "URL of the Azure DevOps organization or the TFS Project Collection to connect to.",
+ }
+ authPersonal := &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ personalAccessTokenExternalTFS: {
+ Type: schema.TypeString,
+ Required: true,
+ DefaultFunc: schema.EnvDefaultFunc("AZDO_PERSONAL_ACCESS_TOKEN", nil),
+ Description: "Personal access tokens are applicable only for connections targeting Azure DevOps organization or TFS 2017 (and higher)",
+ Sensitive: true,
+ ValidateFunc: validation.StringIsNotEmpty,
+ },
+ },
+ }
+ patHashKey, patHashSchema := tfhelper.GenerateSecreteMemoSchema(personalAccessTokenExternalTFS)
+ authPersonal.Schema[patHashKey] = patHashSchema
+ r.Schema["auth_personal"] = &schema.Schema{
+ Type: schema.TypeSet,
+ MinItems: 1,
+ MaxItems: 1,
+ Elem: authPersonal,
+ Required: true,
+ }
+ return r
+}
+
+func expandServiceEndpointExternalTFS(d *schema.ResourceData) (*serviceendpoint.ServiceEndpoint, *uuid.UUID, error) {
+ serviceEndpoint, projectID := doBaseExpansion(d)
+ serviceEndpoint.Type = converter.String("externaltfs")
+ serviceEndpoint.Url = converter.String(d.Get("connection_url").(string))
+
+ scheme := "Token"
+ parameters := map[string]string{}
+
+ if config, ok := d.GetOk("auth_personal"); ok {
+ scheme = "Token"
+ parameters = expandAuthPersonalSetExternalTFS(config.(*schema.Set))
+ }
+
+ serviceEndpoint.Authorization = &serviceendpoint.EndpointAuthorization{
+ Parameters: &parameters,
+ Scheme: &scheme,
+ }
+ return serviceEndpoint, projectID, nil
+}
+
+func expandAuthPersonalSetExternalTFS(d *schema.Set) map[string]string {
+ authPerson := make(map[string]string)
+ val := d.List()[0].(map[string]interface{})
+
+ authPerson["apitoken"] = val[personalAccessTokenExternalTFS].(string)
+ return authPerson
+}
+
+func flattenServiceEndpointExternalTFS(
+ d *schema.ResourceData,
+ serviceEndpoint *serviceendpoint.ServiceEndpoint,
+ projectID *uuid.UUID,
+) {
+ doBaseFlattening(d, serviceEndpoint, projectID)
+
+ if strings.EqualFold(*serviceEndpoint.Authorization.Scheme, "Token") {
+ authPersonalSet := d.Get("auth_personal").(*schema.Set).List()
+ authPersonal := flattenAuthPersonExternalTFS(d, authPersonalSet)
+ if authPersonal != nil {
+ d.Set("auth_personal", authPersonal)
+ }
+ }
+
+ d.Set("connection_url", *serviceEndpoint.Url)
+}
+
+func flattenAuthPersonExternalTFS(d *schema.ResourceData, authPersonalSet []interface{}) []interface{} {
+ if len(authPersonalSet) == 1 {
+ if authPersonal, ok := authPersonalSet[0].(map[string]interface{}); ok {
+ newHash, hashKey := tfhelper.HelpFlattenSecretNested(
+ d,
+ "auth_personal",
+ authPersonal,
+ personalAccessTokenExternalTFS,
+ )
+ authPersonal[hashKey] = newHash
+ return []interface{}{authPersonal}
+ }
+ }
+ return nil
+}
diff --git a/azuredevops/internal/service/serviceendpoint/resource_serviceendpoint_externaltfs_test.go b/azuredevops/internal/service/serviceendpoint/resource_serviceendpoint_externaltfs_test.go
new file mode 100644
index 00000000..fc7fc7be
--- /dev/null
+++ b/azuredevops/internal/service/serviceendpoint/resource_serviceendpoint_externaltfs_test.go
@@ -0,0 +1,192 @@
+//go:build (all || resource_serviceendpoint_externaltfs) && !exclude_serviceendpoints
+// +build all resource_serviceendpoint_externaltfs
+// +build !exclude_serviceendpoints
+
+package serviceendpoint
+
+import (
+ "context"
+ "errors"
+ "testing"
+
+ "github.com/golang/mock/gomock"
+ "github.com/google/uuid"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+ "github.com/microsoft/azure-devops-go-api/azuredevops/v6/serviceendpoint"
+ "github.com/microsoft/terraform-provider-azuredevops/azdosdkmocks"
+ "github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/client"
+ "github.com/microsoft/terraform-provider-azuredevops/azuredevops/internal/utils/converter"
+ "github.com/stretchr/testify/require"
+)
+
+var (
+ externalTfsTestServiceEndpointID = uuid.New()
+ externalTfsRandomServiceEndpointProjectID = uuid.New()
+ externalTfsTestServiceEndpointProjectID = &externalTfsRandomServiceEndpointProjectID
+)
+
+var externalTfsTestServiceEndpoint = serviceendpoint.ServiceEndpoint{
+ Authorization: &serviceendpoint.EndpointAuthorization{
+ Parameters: &map[string]string{
+ "apitoken": "UNIT_TEST_ACCESS_TOKEN",
+ },
+ Scheme: converter.String("Token"),
+ },
+ Id: &externalTfsTestServiceEndpointID,
+ Name: converter.String("UNIT_TEST_NAME"),
+ Owner: converter.String("library"),
+ Type: converter.String("externaltfs"),
+ Url: converter.String("https://dev.azure.com/myorganization"),
+ ServiceEndpointProjectReferences: &[]serviceendpoint.ServiceEndpointProjectReference{
+ {
+ ProjectReference: &serviceendpoint.ProjectReference{
+ Id: externalTfsTestServiceEndpointProjectID,
+ },
+ Name: converter.String("UNIT_TEST_NAME"),
+ Description: converter.String("UNIT_TEST_DESCRIPTION"),
+ },
+ },
+}
+
+func TestServiceEndpointExternalTFS_ExpandFlatten_Roundtrip(t *testing.T) {
+ resourceData := schema.TestResourceDataRaw(t, ResourceServiceEndpointExternalTFS().Schema, nil)
+ configureExternalTfsAuthPersonal(resourceData)
+ flattenServiceEndpointExternalTFS(
+ resourceData,
+ &externalTfsTestServiceEndpoint,
+ externalTfsTestServiceEndpointProjectID,
+ )
+
+ serviceEndpointAfterRoundTrip, projectID, err := expandServiceEndpointExternalTFS(resourceData)
+
+ require.Nil(t, err)
+ require.Equal(t, externalTfsTestServiceEndpoint, *serviceEndpointAfterRoundTrip)
+ require.Equal(t, externalTfsTestServiceEndpointProjectID, projectID)
+}
+
+func TestServiceEndpointExternalTFS_Create_DoesNotSwallowError(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
+ r := ResourceServiceEndpointExternalTFS()
+ resourceData := schema.TestResourceDataRaw(t, r.Schema, nil)
+ configureExternalTfsAuthPersonal(resourceData)
+ flattenServiceEndpointExternalTFS(
+ resourceData,
+ &externalTfsTestServiceEndpoint,
+ externalTfsTestServiceEndpointProjectID,
+ )
+
+ buildClient := azdosdkmocks.NewMockServiceendpointClient(ctrl)
+ clients := &client.AggregatedClient{ServiceEndpointClient: buildClient, Ctx: context.Background()}
+
+ expectedArgs := serviceendpoint.CreateServiceEndpointArgs{Endpoint: &externalTfsTestServiceEndpoint}
+ buildClient.
+ EXPECT().
+ CreateServiceEndpoint(clients.Ctx, expectedArgs).
+ Return(nil, errors.New("CreateServiceEndpoint() Failed")).
+ Times(1)
+
+ err := r.Create(resourceData, clients)
+ require.Contains(t, err.Error(), "CreateServiceEndpoint() Failed")
+}
+
+func TestServiceEndpointExternalTFS_Read_DoesNotSwallowError(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
+ r := ResourceServiceEndpointExternalTFS()
+ resourceData := schema.TestResourceDataRaw(t, r.Schema, nil)
+ flattenServiceEndpointExternalTFS(
+ resourceData,
+ &externalTfsTestServiceEndpoint,
+ externalTfsTestServiceEndpointProjectID,
+ )
+
+ buildClient := azdosdkmocks.NewMockServiceendpointClient(ctrl)
+ clients := &client.AggregatedClient{ServiceEndpointClient: buildClient, Ctx: context.Background()}
+
+ expectedArgs := serviceendpoint.GetServiceEndpointDetailsArgs{
+ EndpointId: externalTfsTestServiceEndpoint.Id,
+ Project: converter.String(externalTfsTestServiceEndpointProjectID.String()),
+ }
+ buildClient.
+ EXPECT().
+ GetServiceEndpointDetails(clients.Ctx, expectedArgs).
+ Return(nil, errors.New("GetServiceEndpoint() Failed")).
+ Times(1)
+
+ err := r.Read(resourceData, clients)
+ require.Contains(t, err.Error(), "GetServiceEndpoint() Failed")
+}
+
+func TestServiceEndpointExternalTFS_Delete_DoesNotSwallowError(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
+ r := ResourceServiceEndpointExternalTFS()
+ resourceData := schema.TestResourceDataRaw(t, r.Schema, nil)
+ flattenServiceEndpointExternalTFS(
+ resourceData,
+ &externalTfsTestServiceEndpoint,
+ externalTfsTestServiceEndpointProjectID,
+ )
+
+ buildClient := azdosdkmocks.NewMockServiceendpointClient(ctrl)
+ clients := &client.AggregatedClient{ServiceEndpointClient: buildClient, Ctx: context.Background()}
+
+ expectedArgs := serviceendpoint.DeleteServiceEndpointArgs{
+ EndpointId: externalTfsTestServiceEndpoint.Id,
+ ProjectIds: &[]string{
+ externalTfsTestServiceEndpointProjectID.String(),
+ },
+ }
+
+ buildClient.
+ EXPECT().
+ DeleteServiceEndpoint(clients.Ctx, expectedArgs).
+ Return(errors.New("DeleteServiceEndpoint() Failed")).
+ Times(1)
+
+ err := r.Delete(resourceData, clients)
+ require.Contains(t, err.Error(), "DeleteServiceEndpoint() Failed")
+}
+
+func TestServiceEndpointExternalTFS_Update_DoesNotSwallowError(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
+ r := ResourceServiceEndpointExternalTFS()
+ resourceData := schema.TestResourceDataRaw(t, r.Schema, nil)
+ configureExternalTfsAuthPersonal(resourceData)
+ flattenServiceEndpointExternalTFS(
+ resourceData,
+ &externalTfsTestServiceEndpoint,
+ externalTfsTestServiceEndpointProjectID,
+ )
+
+ buildClient := azdosdkmocks.NewMockServiceendpointClient(ctrl)
+ clients := &client.AggregatedClient{ServiceEndpointClient: buildClient, Ctx: context.Background()}
+
+ expectedArgs := serviceendpoint.UpdateServiceEndpointArgs{
+ Endpoint: &externalTfsTestServiceEndpoint,
+ EndpointId: externalTfsTestServiceEndpoint.Id,
+ }
+
+ buildClient.
+ EXPECT().
+ UpdateServiceEndpoint(clients.Ctx, expectedArgs).
+ Return(nil, errors.New("UpdateServiceEndpoint() Failed")).
+ Times(1)
+
+ err := r.Update(resourceData, clients)
+ require.Contains(t, err.Error(), "UpdateServiceEndpoint() Failed")
+}
+
+func configureExternalTfsAuthPersonal(d *schema.ResourceData) {
+ d.Set("auth_personal", &[]map[string]interface{}{
+ {
+ personalAccessTokenExternalTFS: "UNIT_TEST_ACCESS_TOKEN",
+ },
+ })
+}
diff --git a/azuredevops/provider.go b/azuredevops/provider.go
index 96229c24..9aa3726b 100644
--- a/azuredevops/provider.go
+++ b/azuredevops/provider.go
@@ -66,6 +66,7 @@ func Provider() *schema.Provider {
"azuredevops_serviceendpoint_npm": serviceendpoint.ResourceServiceEndpointNpm(),
"azuredevops_serviceendpoint_generic": serviceendpoint.ResourceServiceEndpointGeneric(),
"azuredevops_serviceendpoint_generic_git": serviceendpoint.ResourceServiceEndpointGenericGit(),
+ "azuredevops_serviceendpoint_externaltfs": serviceendpoint.ResourceServiceEndpointExternalTFS(),
"azuredevops_git_repository": git.ResourceGitRepository(),
"azuredevops_git_repository_file": git.ResourceGitRepositoryFile(),
"azuredevops_user_entitlement": memberentitlementmanagement.ResourceUserEntitlement(),
diff --git a/azuredevops/provider_test.go b/azuredevops/provider_test.go
index b5c27fb9..92d264c7 100644
--- a/azuredevops/provider_test.go
+++ b/azuredevops/provider_test.go
@@ -43,6 +43,7 @@ func TestProvider_HasChildResources(t *testing.T) {
"azuredevops_serviceendpoint_generic_git",
"azuredevops_serviceendpoint_octopusdeploy",
"azuredevops_serviceendpoint_incomingwebhook",
+ "azuredevops_serviceendpoint_externaltfs",
"azuredevops_variable_group",
"azuredevops_repository_policy_author_email_pattern",
"azuredevops_repository_policy_case_enforcement",