Skip to content
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

FEATURES:

- **New Resource:** `netapp-ontap_fpolicy_event` ([#624](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/624))
- **New Data Source:** `netapp-ontap_network_ip_service_policy` and `netapp-ontap_network_ip_service_policies`([#621](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/621))
- **New Resource:** `netapp-ontap_network_ip_service_policy` ([#621](https://github.com/NetApp/terraform-provider-netapp-ontap/issues/621))

Expand Down
100 changes: 100 additions & 0 deletions docs/resources/fpolicy_event.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "netapp-ontap_fpolicy_event Resource - terraform-provider-netapp-ontap"
subcategory: "Protocols"
description: |-
FPolicy event resource
---

# netapp-ontap_fpolicy_event (Resource)

Creates, updates, and deletes an FPolicy event resource.

## Example Usage

```terraform
resource "netapp-ontap_fpolicy_event" "example" {
cx_profile_name = "cluster1"
name = "event1"
svm_name = "svm1"
protocol = "cifs"
file_operations = ["create", "write", "close"]
filters = ["monitor_ads"]
volume_monitoring = false
}
```

## Argument Reference

The following arguments are supported:

### Required

- `cx_profile_name` - (String) Connection profile name.
- `name` - (String) Specifies the name of the FPolicy event. This field cannot be changed after creation.
- `svm_name` - (String) Name of the SVM to which this FPolicy event belongs. This field cannot be changed after creation.

### Optional

- `protocol` - (String) Protocol for which the FPolicy event is applicable. Valid values are `cifs`, `nfsv3`, or `nfsv4`.
- `file_operations` - (Set of String) File operations to be monitored. Examples: `create`, `write`, `read`, `close`, `rename`, `delete`, `open`, `getattr`, `setattr`.
- `filters` - (Set of String) Filters to be applied for the specified file operations. Examples: `monitor_ads`, `close_with_modification`, `close_without_modification`, `first_read`, `first_write`, `offline_bit`, `open_with_delete_intent`, `open_with_write_intent`, `write_with_size_change`.
- `volume_monitoring` - (Bool) Specifies whether volume operation monitoring is required.

### Read-Only

- `id` - (String) FPolicy event identifier in the format `svm_name/event_name`.

## Import

This resource supports import, which allows you to import existing FPolicy events into the state.
Import require a unique ID composed of the event name, SVM name, and the connection profile, separated by a comma.

id = `name`,`svm_name`,`cx_profile_name`

### Terraform Import

For example

```shell
terraform import netapp-ontap_fpolicy_event.example event1,svm1,cluster4
```

!> The terraform import CLI command can only import resources into the state. Importing via the CLI does not generate configuration. If you want to generate the accompanying configuration for imported resources, use the import block instead.

### Terraform Import Block

This requires Terraform 1.5 or higher, and will auto create the configuration for you

First create the block

```terraform
import {
to = netapp-ontap_fpolicy_event.fpolicy_import
id = "event1,svm1,cluster4"
}
```

Next run, this will auto create the configuration for you

```shell
terraform plan -generate-config-out=generated.tf
```

This will generate a file called generated.tf, which will contain the configuration for the imported resource

```terraform
# __generated__ by Terraform
# Please review these resources and move them into your main configuration files.

# __generated__ by Terraform from "event1,svm1,cluster4"
resource "netapp-ontap_fpolicy_event" "fpolicy_import" {
cx_profile_name = "cluster4"
name = "event1"
svm_name = "svm1"
protocol = "cifs"
file_operations = ["create", "write", "close"]
filters = ["monitor_ads"]
volume_monitoring = false
}
```
Copy link
Contributor

@chuyich chuyich Jan 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

provider.tf should be a link pointing to https://github.com/NetApp/terraform-provider-netapp-ontap/blob/integration/main/examples/provider/provider.tf
If there are some new clusters, please update the canvas on the dev-terraform-ontap channel

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is still a file not a link

21 changes: 21 additions & 0 deletions examples/resources/netapp-ontap_fpolicy_event/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
resource "netapp-ontap_fpolicy_event" "protocols_fpolicy_event_cifs" {
# required to know which system to interface with
cx_profile_name = "cluster1"
name = "event_test"
svm_name = "tf_acc_svm"
protocol = "cifs"
file_operations = ["create", "write", "close", "rename", "delete"]
filters = ["monitor_ads", "close_with_modification"]
volume_monitoring = false
}

resource "netapp-ontap_fpolicy_event" "protocols_fpolicy_event_nfs" {
# required to know which system to interface with
cx_profile_name = "cluster1"
name = "event_test2"
svm_name = "tf_acc_svm"
protocol = "nfsv4"
file_operations = ["create", "write", "read", "open", "close"]
# filters = ["first_read", "first_write", "write_with_size_change"]
# volume_monitoring = false
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is still a file not a link.

192 changes: 192 additions & 0 deletions internal/interfaces/protocols_fpolicy_event.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
package interfaces

import (
"fmt"

"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/mitchellh/mapstructure"
"github.com/netapp/terraform-provider-netapp-ontap/internal/restclient"
"github.com/netapp/terraform-provider-netapp-ontap/internal/utils"
)

// FpolicyEventFileOperations describes file operations model
type FpolicyEventFileOperations struct {
Access bool `mapstructure:"access"`
Close bool `mapstructure:"close"`
Create bool `mapstructure:"create"`
CreateDir bool `mapstructure:"create_dir"`
Delete bool `mapstructure:"delete"`
DeleteDir bool `mapstructure:"delete_dir"`
GetAttr bool `mapstructure:"getattr"`
Link bool `mapstructure:"link"`
Lookup bool `mapstructure:"lookup"`
Open bool `mapstructure:"open"`
Read bool `mapstructure:"read"`
Rename bool `mapstructure:"rename"`
RenameDir bool `mapstructure:"rename_dir"`
SetAttr bool `mapstructure:"setattr"`
Symlink bool `mapstructure:"symlink"`
Write bool `mapstructure:"write"`
}

// FpolicyEventFilters describes filters model
type FpolicyEventFilters struct {
CloseWithModification bool `mapstructure:"close_with_modification"`
CloseWithRead bool `mapstructure:"close_with_read"`
CloseWithoutModification bool `mapstructure:"close_without_modification"`
ExcludeDirectory bool `mapstructure:"exclude_directory"`
FirstRead bool `mapstructure:"first_read"`
FirstWrite bool `mapstructure:"first_write"`
MonitorAds bool `mapstructure:"monitor_ads"`
OfflineBit bool `mapstructure:"offline_bit"`
OpenWithDeleteIntent bool `mapstructure:"open_with_delete_intent"`
OpenWithWriteIntent bool `mapstructure:"open_with_write_intent"`
SetAttrWithAccessTimeChange bool `mapstructure:"setattr_with_access_time_change"`
SetAttrWithAllocationSizeChange bool `mapstructure:"setattr_with_allocation_size_change"`
SetAttrWithCreationTimeChange bool `mapstructure:"setattr_with_creation_time_change"`
SetAttrWithDaclChange bool `mapstructure:"setattr_with_dacl_change"`
SetAttrWithGroupChange bool `mapstructure:"setattr_with_group_change"`
SetAttrWithModeChange bool `mapstructure:"setattr_with_mode_change"`
SetAttrWithModifyTimeChange bool `mapstructure:"setattr_with_modify_time_change"`
SetAttrWithOwnerChange bool `mapstructure:"setattr_with_owner_change"`
SetAttrWithSaclChange bool `mapstructure:"setattr_with_sacl_change"`
SetAttrWithSizeChange bool `mapstructure:"setattr_with_size_change"`
WriteWithSizeChange bool `mapstructure:"write_with_size_change"`
}

// ProtocolsFpolicyEventGetDataModelONTAP describes the GET record data model using go types for mapping.
type ProtocolsFpolicyEventGetDataModelONTAP struct {
Name string `mapstructure:"name"`
Protocol string `mapstructure:"protocol"`
FileOperations FpolicyEventFileOperations `mapstructure:"file_operations"`
Filters FpolicyEventFilters `mapstructure:"filters"`
VolumeMonitoring *bool `mapstructure:"volume_monitoring"`
SVM SvmDataModelONTAP `mapstructure:"svm"`
}

// ProtocolsFpolicyEventResourceBodyDataModelONTAP describes the body data model using go types for mapping.
type ProtocolsFpolicyEventResourceBodyDataModelONTAP struct {
Name string `mapstructure:"name"`
Protocol string `mapstructure:"protocol,omitempty"`
FileOperations FpolicyEventFileOperations `mapstructure:"file_operations,omitempty"`
Filters FpolicyEventFilters `mapstructure:"filters,omitempty"`
VolumeMonitoring bool `mapstructure:"volume_monitoring"`
}

// ProtocolsFpolicyEventResourceUpdateBodyDataModelONTAP describes the update body data model (for PATCH - without name field)
type ProtocolsFpolicyEventResourceUpdateBodyDataModelONTAP struct {
Protocol string `mapstructure:"protocol,omitempty"`
FileOperations FpolicyEventFileOperations `mapstructure:"file_operations,omitempty"`
Filters FpolicyEventFilters `mapstructure:"filters,omitempty"`
VolumeMonitoring *bool `mapstructure:"volume_monitoring"`
}

// ProtocolsFpolicyEventDataSourceFilterModel describes filter model
type ProtocolsFpolicyEventDataSourceFilterModel struct {
Name string `mapstructure:"name"`
SVMName string `mapstructure:"svm.name"`
}

// GetProtocolsFpolicyEventByName to get protocols_fpolicy_event info
func GetProtocolsFpolicyEventByName(errorHandler *utils.ErrorHandler, r restclient.RestClient, name string, svmUUID string) (*ProtocolsFpolicyEventGetDataModelONTAP, error) {
api := fmt.Sprintf("protocols/fpolicy/%s/events/%s", svmUUID, name)
query := r.NewQuery()
query.Set("return_timeout", "15")
query.Fields([]string{"name", "protocol", "file_operations", "filters", "volume_monitoring", "svm"})

statusCode, response, err := r.GetNilOrOneRecord(api, query, nil)
if err != nil {
return nil, errorHandler.MakeAndReportError("error reading protocols_fpolicy_event info", fmt.Sprintf("error on GET %s: %s, statusCode %d", api, err, statusCode))
}

var dataONTAP ProtocolsFpolicyEventGetDataModelONTAP
if err := mapstructure.Decode(response, &dataONTAP); err != nil {
return nil, errorHandler.MakeAndReportError(fmt.Sprintf("failed to decode response from GET %s", api),
fmt.Sprintf("error: %s, statusCode %d, response %#v", err, statusCode, response))
}
tflog.Debug(errorHandler.Ctx, fmt.Sprintf("Read protocols_fpolicy_event source - udata: %#v", dataONTAP))
return &dataONTAP, nil
}

// GetProtocolsFpolicyEvents to get protocols_fpolicy_event info for all resources matching a filter
func GetProtocolsFpolicyEvents(errorHandler *utils.ErrorHandler, r restclient.RestClient, filter *ProtocolsFpolicyEventDataSourceFilterModel) ([]ProtocolsFpolicyEventGetDataModelONTAP, error) {
api := "protocols/fpolicy/*/events"
query := r.NewQuery()
query.Set("return_timeout", "15")
query.Fields([]string{"name", "protocol", "file_operations", "filters", "volume_monitoring", "svm"})

if filter != nil {
var filterMap map[string]interface{}
if err := mapstructure.Decode(filter, &filterMap); err != nil {
return nil, errorHandler.MakeAndReportError("error encoding protocols_fpolicy_events filter info", fmt.Sprintf("error on filter %#v: %s", filter, err))
}
query.SetValues(filterMap)
}

statusCode, response, err := r.GetZeroOrMoreRecords(api, query, nil)
if err != nil {
return nil, errorHandler.MakeAndReportError("error reading protocols_fpolicy_event info", fmt.Sprintf("error on GET %s: %s, statusCode %d", api, err, statusCode))
}

var dataONTAP []ProtocolsFpolicyEventGetDataModelONTAP
for _, info := range response {
var record ProtocolsFpolicyEventGetDataModelONTAP
if err := mapstructure.Decode(info, &record); err != nil {
return nil, errorHandler.MakeAndReportError(fmt.Sprintf("failed to decode response from GET %s", api),
fmt.Sprintf("error: %s, statusCode %d, info %#v", err, statusCode, info))
}
dataONTAP = append(dataONTAP, record)
}
tflog.Debug(errorHandler.Ctx, fmt.Sprintf("Read protocols_fpolicy_events data source: %#v", dataONTAP))
return dataONTAP, nil
}

// CreateProtocolsFpolicyEvent to create protocols_fpolicy_event
func CreateProtocolsFpolicyEvent(errorHandler *utils.ErrorHandler, r restclient.RestClient, body ProtocolsFpolicyEventResourceBodyDataModelONTAP, svmUUID string) (*ProtocolsFpolicyEventGetDataModelONTAP, error) {
api := fmt.Sprintf("protocols/fpolicy/%s/events", svmUUID)
var bodyMap map[string]interface{}
if err := mapstructure.Decode(body, &bodyMap); err != nil {
return nil, errorHandler.MakeAndReportError("error encoding protocols_fpolicy_event body", fmt.Sprintf("error on encoding %s body: %s, body: %#v", api, err, body))
}
query := r.NewQuery()
query.Set("return_records", "true")

statusCode, response, err := r.CallCreateMethod(api, query, bodyMap)
if err != nil {
return nil, errorHandler.MakeAndReportError("error creating protocols_fpolicy_event", fmt.Sprintf("error on POST %s: %s, statusCode %d", api, err, statusCode))
}

var dataONTAP ProtocolsFpolicyEventGetDataModelONTAP
if err := mapstructure.Decode(response.Records[0], &dataONTAP); err != nil {
return nil, errorHandler.MakeAndReportError("error decoding protocols_fpolicy_event info", fmt.Sprintf("error on decode storage/protocols_fpolicy_events info: %s, statusCode %d, response %#v", err, statusCode, response))
}
tflog.Debug(errorHandler.Ctx, fmt.Sprintf("Create protocols_fpolicy_event source - udata: %#v", dataONTAP))
return &dataONTAP, nil
}

// UpdateProtocolsFpolicyEvent to update protocols_fpolicy_event
func UpdateProtocolsFpolicyEvent(errorHandler *utils.ErrorHandler, r restclient.RestClient, body ProtocolsFpolicyEventResourceUpdateBodyDataModelONTAP, svmUUID string, name string) error {
api := fmt.Sprintf("protocols/fpolicy/%s/events/%s", svmUUID, name)
var bodyMap map[string]interface{}
if err := mapstructure.Decode(body, &bodyMap); err != nil {
return errorHandler.MakeAndReportError("error encoding protocols_fpolicy_event body", fmt.Sprintf("error on encoding %s body: %s, body: %#v", api, err, body))
}
query := r.NewQuery()
query.Set("return_timeout", "15")

statusCode, _, err := r.CallUpdateMethod(api, query, bodyMap)
if err != nil {
return errorHandler.MakeAndReportError("error updating protocols_fpolicy_event", fmt.Sprintf("error on PATCH %s: %s, statusCode %d", api, err, statusCode))
}
return nil
}

// DeleteProtocolsFpolicyEvent to delete protocols_fpolicy_event
func DeleteProtocolsFpolicyEvent(errorHandler *utils.ErrorHandler, r restclient.RestClient, svmUUID string, name string) error {
api := fmt.Sprintf("protocols/fpolicy/%s/events/%s", svmUUID, name)
statusCode, _, err := r.CallDeleteMethod(api, nil, nil)
if err != nil {
return errorHandler.MakeAndReportError("error deleting protocols_fpolicy_event", fmt.Sprintf("error on DELETE %s: %s, statusCode %d", api, err, statusCode))
}
return nil
}
Loading
Loading