Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Resource: azurerm_automation_private_endpoint_connection #17935

Closed
wants to merge 1 commit into from
Closed
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
package automation

import (
"context"
"fmt"
"time"

"github.com/Azure/azure-sdk-for-go/services/preview/automation/mgmt/2020-01-13-preview/automation"

"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/automation/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/automation/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

type PrivateEndpointConnectionModel struct {
ResourceGroupName string `tfschema:"resource_group_name"`
AutomationAccountName string `tfschema:"automation_account_name"`
Name string `tfschema:"name"`
LinkStatus string `tfschema:"link_status"`
LinkDescription string `tfschema:"link_description"`
LinkActionRequired string `tfschema:"link_action_required"`
PrivateEndpointID string `tfschema:"private_endpoint_id"`
GroupIds []string `tfschema:"group_ids"`
}

type PrivateEndpointConnectionResource struct{}

var _ sdk.Resource = (*PrivateEndpointConnectionResource)(nil)

func (m PrivateEndpointConnectionResource) Arguments() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"resource_group_name": commonschema.ResourceGroupName(),
"automation_account_name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringIsNotEmpty,
},
"name": {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringIsNotEmpty,
},
"link_status": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validation.StringIsNotEmpty,
},
"link_description": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validation.StringIsNotEmpty,
},
}
}

func (m PrivateEndpointConnectionResource) Attributes() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"group_ids": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
},
"link_action_required": {
Type: pluginsdk.TypeString,
Computed: true,
},
"private_endpoint_id": {
Type: pluginsdk.TypeString,
Computed: true,
},
}
}

func (m PrivateEndpointConnectionResource) ModelObject() interface{} {
return &PrivateEndpointConnectionModel{}
}

func (m PrivateEndpointConnectionResource) ResourceType() string {
return "azurerm_automation_private_endpoint_connection"
}

func (m PrivateEndpointConnectionResource) Create() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, meta sdk.ResourceMetaData) error {
client := meta.Client.Automation.PrivateEndpointClient

var model PrivateEndpointConnectionModel
if err := meta.Decode(&model); err != nil {
return err
}

subscriptionID := meta.Client.Account.SubscriptionId
id := parse.NewPrivateEndpointConnectionID(subscriptionID, model.ResourceGroupName,
model.AutomationAccountName, model.Name)
existing, err := client.Get(ctx, id.ResourceGroup, id.AutomationAccountName, id.Name)
if err != nil {
return fmt.Errorf("retreiving %s: %v", id, err)
}
if utils.ResponseWasNotFound(existing.Response) {
return fmt.Errorf("no such private endpoint connection: %v", id)
}

var params automation.PrivateEndpointConnection
params.PrivateEndpointConnectionProperties = &automation.PrivateEndpointConnectionProperties{
PrivateLinkServiceConnectionState: &automation.PrivateLinkServiceConnectionStateProperty{},
}
if model.LinkStatus != "" {
params.PrivateLinkServiceConnectionState.Status = utils.String(model.LinkStatus)
}
if model.LinkDescription != "" {
params.PrivateLinkServiceConnectionState.Description = utils.String(model.LinkDescription)
}
future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.AutomationAccountName, id.Name, params)
if err != nil {
return fmt.Errorf("creating %s: %v", id, err)
}
// TODO may not need wait, delete lines below
if err := future.WaitForCompletionRef(ctx, client.Client); err != nil {
return fmt.Errorf("waiting for creation of %s: %v", id, err)
}

meta.SetID(id)
return nil
},
}
}

func (m PrivateEndpointConnectionResource) Read() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, meta sdk.ResourceMetaData) error {
id, err := parse.PrivateEndpointConnectionID(meta.ResourceData.Id())
if err != nil {
return err
}
client := meta.Client.Automation.PrivateEndpointClient
result, err := client.Get(ctx, id.ResourceGroup, id.AutomationAccountName, id.Name)
if err != nil {
return err
}

var output PrivateEndpointConnectionModel
output.Name = id.Name
output.ResourceGroupName = id.ResourceGroup
output.AutomationAccountName = id.AutomationAccountName
if result.PrivateEndpoint != nil {
output.PrivateEndpointID = utils.NormalizeNilableString(result.PrivateEndpoint.ID)
}
if prop := result.PrivateEndpointConnectionProperties; prop != nil {
if state := prop.PrivateLinkServiceConnectionState; state != nil {
output.LinkStatus = utils.NormalizeNilableString(state.Status)
output.LinkDescription = utils.NormalizeNilableString(state.Description)
output.LinkActionRequired = utils.NormalizeNilableString(state.ActionsRequired)
}
if point := prop.PrivateEndpoint; point != nil {
output.PrivateEndpointID = utils.NormalizeNilableString(point.ID)
}
// no group id in definition
}
return meta.Encode(&output)
},
}
}

func (m PrivateEndpointConnectionResource) Update() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 10 * time.Minute,
Func: func(ctx context.Context, meta sdk.ResourceMetaData) (err error) {
client := meta.Client.Automation.PrivateEndpointClient

id, err := parse.PrivateEndpointConnectionID(meta.ResourceData.Id())
if err != nil {
return err
}

var model PrivateEndpointConnectionModel
if err = meta.Decode(&model); err != nil {
return fmt.Errorf("decoding err: %+v", err)
}

var upd automation.PrivateEndpointConnection
upd.PrivateEndpointConnectionProperties = &automation.PrivateEndpointConnectionProperties{}
upd.PrivateEndpointConnectionProperties.PrivateLinkServiceConnectionState = &automation.PrivateLinkServiceConnectionStateProperty{}
if meta.ResourceData.HasChange("link_status") {
upd.PrivateLinkServiceConnectionState.Status = utils.String(model.LinkStatus)
}
if meta.ResourceData.HasChange("link_description") {
upd.PrivateLinkServiceConnectionState.Description = utils.String(model.LinkDescription)
}
if _, err = client.CreateOrUpdate(ctx, id.ResourceGroup, id.AutomationAccountName, id.Name, upd); err != nil {
return fmt.Errorf("updating %s: %v", id, err)
}

return nil
},
}
}

func (m PrivateEndpointConnectionResource) Delete() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 10 * time.Minute,
Func: func(ctx context.Context, meta sdk.ResourceMetaData) error {
id, err := parse.PrivateEndpointConnectionID(meta.ResourceData.Id())
if err != nil {
return err
}
meta.Logger.Infof("deleting %s", id)
client := meta.Client.Automation.PrivateEndpointClient
if _, err = client.Delete(ctx, id.ResourceGroup, id.AutomationAccountName, id.Name); err != nil {
return fmt.Errorf("deleting %s: %v", id, err)
}
return nil
},
}
}

func (m PrivateEndpointConnectionResource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return validate.PrivateEndpointConnectionID
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package automation_test

import (
"context"
"fmt"
"testing"

"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance"
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/automation"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/automation/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

type PrivateEndpointConnectionResource struct{}

func (a PrivateEndpointConnectionResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := parse.PrivateEndpointConnectionID(state.ID)
if err != nil {
return nil, err
}
resp, err := client.Automation.PrivateEndpointClient.Get(ctx, id.ResourceGroup, id.AutomationAccountName, id.Name)
if err != nil {
return nil, fmt.Errorf("retrieving Type %s: %+v", id, err)
}
return utils.Bool(resp.PrivateEndpointConnectionProperties != nil), nil
}

func (a PrivateEndpointConnectionResource) template(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

data "azurerm_subscription" "current" {}

resource "azurerm_resource_group" "test" {
name = "acctestRG-auto-%[1]d"
location = "%[2]s"
}

resource "azurerm_virtual_network" "test" {
name = "acctestvnet-%[1]d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
address_space = ["10.5.0.0/16"]
}

resource "azurerm_subnet" "endpoint" {
name = "acctestsnetendpoint-%[1]d"
resource_group_name = azurerm_resource_group.test.name
virtual_network_name = azurerm_virtual_network.test.name
address_prefixes = ["10.5.2.0/24"]

enforce_private_link_endpoint_network_policies = true
}

resource "azurerm_private_endpoint" "test" {
name = "acctest-pe-%[1]d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
subnet_id = azurerm_subnet.endpoint.id

private_service_connection {
name = azurerm_automation_account.test.name
is_manual_connection = true
private_connection_resource_id = azurerm_automation_account.test.id
subresource_names = ["Webhook"]
request_message = "abc"
}
}

resource "azurerm_automation_account" "test" {
name = "acctestAA-%[1]d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
sku_name = "Basic"
}
`, data.RandomInteger, data.Locations.Primary)
}

func (a PrivateEndpointConnectionResource) basic(data acceptance.TestData) string {
return fmt.Sprintf(`




%s

data "azurerm_automation_account" "test" {
name = azurerm_automation_account.test.name
resource_group_name = azurerm_resource_group.test.name
depends_on = [azurerm_private_endpoint.test]
}

resource "azurerm_automation_private_endpoint_connection" "test" {
name = data.azurerm_automation_account.test.private_endpoint_connection[0].name
resource_group_name = azurerm_resource_group.test.name
automation_account_name = azurerm_automation_account.test.name
link_status = "Approved"
link_description = "test description"

depends_on = [azurerm_private_endpoint.test]
}
`, a.template(data))
}

func (a PrivateEndpointConnectionResource) update(data acceptance.TestData) string {
return fmt.Sprintf(`


%s

data "azurerm_automation_account" "test" {
name = azurerm_automation_account.test.name
resource_group_name = azurerm_resource_group.test.name
}

resource "azurerm_automation_private_endpoint_connection" "test" {
name = azurerm_automation_account.test.private_endpoint_connection[0].name
resource_group_name = azurerm_resource_group.test.name
automation_account_name = azurerm_automation_account.test.name
link_status = "Rejected"
link_description = "approved 2"
}
`, a.template(data))
}

func TestAccPrivateEndpointConnection_basic(t *testing.T) {
data := acceptance.BuildTestData(t, automation.PrivateEndpointConnectionResource{}.ResourceType(), "test")
r := PrivateEndpointConnectionResource{}
data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.basic(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccPrivateEndpointConnection_update(t *testing.T) {
data := acceptance.BuildTestData(t, automation.PrivateEndpointConnectionResource{}.ResourceType(), "test")
r := PrivateEndpointConnectionResource{}
data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.basic(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.update(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}
Loading