Skip to content

Commit

Permalink
feat: add broadcast_domains data source
Browse files Browse the repository at this point in the history
  • Loading branch information
acch committed Nov 4, 2024
1 parent e433085 commit 3db158a
Show file tree
Hide file tree
Showing 7 changed files with 257 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
data "netapp-ontap_network_broadcast_domains" "example" {
# required to know which system to interface with
cx_profile_name = "svacluster"
filter = {
ipspace = "Default"
name = "*"
}
}
61 changes: 59 additions & 2 deletions internal/interfaces/networking_broadcast_domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func GetBroadcastDomain(errorHandler *utils.ErrorHandler, r restclient.RestClien
"ports",
"uuid",
})

statusCode, response, err := r.GetNilOrOneRecord(api, query, nil)
if err == nil && response == nil {
err = fmt.Errorf("no broadcast-domain with id '%s' found", id)
Expand All @@ -71,9 +72,12 @@ func GetBroadcastDomain(errorHandler *utils.ErrorHandler, r restclient.RestClien
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))
fmt.Sprintf("error: %s, statusCode %d, response %#v", err, statusCode, response),
)
}

tflog.Debug(errorHandler.Ctx, fmt.Sprintf("Read broadcast_domain data source: %#v", dataONTAP))

return &dataONTAP, nil
}

Expand All @@ -90,6 +94,7 @@ func GetBroadcastDomainByName(errorHandler *utils.ErrorHandler, r restclient.Res
"ports",
"uuid",
})

statusCode, response, err := r.GetNilOrOneRecord(api, query, nil)
if err == nil && response == nil {
err = fmt.Errorf("no broadcast-domain with ipspace '%s' and name '%s' found", ipspace, name)
Expand All @@ -105,8 +110,60 @@ func GetBroadcastDomainByName(errorHandler *utils.ErrorHandler, r restclient.Res
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))
fmt.Sprintf("error: %s, statusCode %d, response %#v", err, statusCode, response),
)
}

tflog.Debug(errorHandler.Ctx, fmt.Sprintf("Read broadcast_domain data source: %#v", dataONTAP))

return &dataONTAP, nil
}

// GetListBroadcastDomains to get broadcast_domain info for all resources matching a filter
func GetListBroadcastDomains(errorHandler *utils.ErrorHandler, r restclient.RestClient, filter *BroadcastDomainDataSourceFilterModel) ([]BroadcastDomainGetDataModelONTAP, error) {
api := "network/ethernet/broadcast-domains/"
query := r.NewQuery()
query.Fields([]string{
"ipspace",
"mtu",
"name",
"ports",
"uuid",
})

if filter != nil {
if filter.IPspace != "" {
query.Set("ipspace", filter.IPspace)
}
if filter.Name != "" {
query.Set("name", filter.Name)
}
}

statusCode, response, err := r.GetZeroOrMoreRecords(api, query, nil)
if err == nil && response == nil {
err = fmt.Errorf("no broadcast-domains with ipspace '%s' and name '%s' found", filter.IPspace, filter.Name)
}
if err != nil {
return nil, errorHandler.MakeAndReportError(
"error reading broadcast-domains info",
fmt.Sprintf("error on GET %s: %s, statusCode %d", api, err, statusCode),
)
}

var dataONTAP []BroadcastDomainGetDataModelONTAP
for _, info := range response {
var record BroadcastDomainGetDataModelONTAP
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 broadcast_domain data source: %#v", dataONTAP))

return dataONTAP, nil
}
186 changes: 186 additions & 0 deletions internal/provider/networking/network_broadcast_domains_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
package networking

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/netapp/terraform-provider-netapp-ontap/internal/interfaces"
"github.com/netapp/terraform-provider-netapp-ontap/internal/provider/connection"
"github.com/netapp/terraform-provider-netapp-ontap/internal/utils"
)

// Ensure provider defined types fully satisfy framework interfaces
var _ datasource.DataSource = &BroadcastDomainsDataSource{}

// NewBroadcastDomainDataSource is a helper function to simplify the provider implementation.
func NewBroadcastDomainsDataSource() datasource.DataSource {
return &BroadcastDomainsDataSource{
config: connection.ResourceOrDataSourceConfig{
Name: "network_broadcast_domains",
},
}
}

// BroadcastDomainsDataSource defines the data source implementation.
type BroadcastDomainsDataSource struct {
config connection.ResourceOrDataSourceConfig
}

// BroadcastDomainsDataSourceModel describes the data source data model.
type BroadcastDomainsDataSourceModel struct {
CxProfileName types.String `tfsdk:"cx_profile_name"`
BroadcastDomains []BroadcastDomainDataSourceModel `tfsdk:"broadcast_domains"`
Filter *BroadcastDomainDataSourceFilterModel `tfsdk:"filter"`
}

// BroadcastDomainDataSourceFilterModel describes the data source data model for queries.
type BroadcastDomainDataSourceFilterModel struct {
IPspace types.String `tfsdk:"ipspace"`
Name types.String `tfsdk:"name"`
}

// Metadata returns the data source type name.
func (d *BroadcastDomainsDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_" + d.config.Name
}

// Schema defines the schema for the data source.
func (d *BroadcastDomainsDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
// This description is used by the documentation generator and the language server.
MarkdownDescription: "Broadcast Domains data source",

Attributes: map[string]schema.Attribute{
"cx_profile_name": schema.StringAttribute{
MarkdownDescription: "Connection profile name",
Required: true,
},
"filter": schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{
"ipspace": schema.StringAttribute{
MarkdownDescription: "Name of the IPspace",
Optional: true,
},
"name": schema.StringAttribute{
MarkdownDescription: "Name of the broadcast domain, scoped to its IPspace",
Optional: true,
},
},
Optional: true,
},
"broadcast_domains": schema.ListNestedAttribute{
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"ipspace": schema.StringAttribute{
MarkdownDescription: "Name of the IPspace",
Computed: true,
},
"name": schema.StringAttribute{
MarkdownDescription: "Name of the broadcast domain, scoped to its IPspace",
Computed: true,
},
"mtu": schema.Int64Attribute{
MarkdownDescription: "Maximum transmission unit, largest packet size on this network",
Computed: true,
},
"ports": schema.ListAttribute{
ElementType: types.StringType,
MarkdownDescription: "Ports that belong to the broadcast domain",
Computed: true,
},
"id": schema.StringAttribute{
MarkdownDescription: "Broadcast domain UUID",
Computed: true,
},
},
},
Computed: true,
},
},
}
}

// Configure adds the provider configured client to the data source.
func (d *BroadcastDomainsDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
// Prevent panic if the provider has not been configured.
if req.ProviderData == nil {
return
}

config, ok := req.ProviderData.(connection.Config)

if !ok {
resp.Diagnostics.AddError(
"Unexpected Data Source Configure Type",
fmt.Sprintf("Expected Config, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)

return
}

d.config.ProviderConfig = config
}

// Read refreshes the Terraform state with the latest data.
func (d *BroadcastDomainsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data BroadcastDomainsDataSourceModel

// Read Terraform configuration data into the model
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

// Use existing-, or create new REST API client
errorHandler := utils.NewErrorHandler(ctx, &resp.Diagnostics)
// we need to defer setting the client until we can read the connection profile name
client, err := connection.GetRestClient(errorHandler, d.config, data.CxProfileName)
if err != nil {
// error reporting done inside NewClient
return
}

// Prepare filter
var filter *interfaces.BroadcastDomainDataSourceFilterModel = nil
if data.Filter != nil {
filter = &interfaces.BroadcastDomainDataSourceFilterModel{
IPspace: data.Filter.IPspace.ValueString(),
Name: data.Filter.Name.ValueString(),
}
}

// Call ONTAP REST API for reading broadcast_domain info
restInfo, err := interfaces.GetListBroadcastDomains(errorHandler, *client, filter)
if err != nil {
// error reporting done inside GetListBroadcastDomains
return
}

// Copy broadcast_domain info to data source model
data.BroadcastDomains = make([]BroadcastDomainDataSourceModel, len(restInfo))
for index, record := range restInfo {
var ports []types.String
for _, v := range record.Ports {
ports = append(ports, types.StringValue(v.Name))
}
data.BroadcastDomains[index] = BroadcastDomainDataSourceModel{
IPSpace: types.StringValue(record.IPspace.Name),
Name: types.StringValue(record.Name),
MTU: types.Int64Value(record.MTU),
Ports: ports,
ID: types.StringValue(record.UUID),
}
}

// Write logs using the tflog package
// Documentation: https://terraform.io/plugin/log
tflog.Debug(ctx, fmt.Sprintf("read a data source: %#v", data))

// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ func (p *ONTAPProvider) DataSources(ctx context.Context) []func() datasource.Dat
name_services.NewNameServicesLDAPDataSource,
name_services.NewNameServicesLDAPsDataSource,
networking.NewBroadcastDomainDataSource,
networking.NewBroadcastDomainsDataSource,
networking.NewIPInterfaceDataSource,
networking.NewIPInterfacesDataSource,
networking.NewIPRouteDataSource,
Expand Down

0 comments on commit 3db158a

Please sign in to comment.