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

add the code and test for the telemetry service registry entry providers #706

Merged
125 changes: 125 additions & 0 deletions apstra/analytics/telemetry_service_registry_entry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package analytics

import (
"context"
"github.com/Juniper/apstra-go-sdk/apstra"
"github.com/Juniper/terraform-provider-apstra/apstra/utils"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
dataSourceSchema "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/diag"
resourceSchema "github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
)

type TelemetryServiceRegistryEntry struct {
ServiceName types.String `tfsdk:"service_name"`
ApplicationSchema types.String `tfsdk:"application_schema"`
rajagopalans marked this conversation as resolved.
Show resolved Hide resolved
StorageSchemaPath types.String `tfsdk:"storage_schema_path"`
Builtin types.Bool `tfsdk:"built_in"`
Description types.String `tfsdk:"description"`
Version types.String `tfsdk:"version"`
}

func (o TelemetryServiceRegistryEntry) ResourceAttributes() map[string]resourceSchema.Attribute {
return map[string]resourceSchema.Attribute{
"service_name": resourceSchema.StringAttribute{
MarkdownDescription: "Service Name. Used to identify the Service.",
Required: true,
Validators: []validator.String{stringvalidator.LengthAtLeast(1)},
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
},
"application_schema": resourceSchema.StringAttribute{
MarkdownDescription: "Application Schema expressed in Json schema",
Required: true,
PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()},
rajagopalans marked this conversation as resolved.
Show resolved Hide resolved
},
"storage_schema_path": resourceSchema.StringAttribute{
MarkdownDescription: "Storage Schema Path",
Required: true,
Validators: []validator.String{
stringvalidator.LengthAtLeast(1),
},
},
"description": resourceSchema.StringAttribute{
MarkdownDescription: "Description",
Optional: true,
Validators: []validator.String{
stringvalidator.LengthAtLeast(1),
},
},
"version": resourceSchema.StringAttribute{
MarkdownDescription: "Version",
Optional: true,
Computed: true,
Validators: []validator.String{
stringvalidator.LengthAtLeast(1),
},
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
rajagopalans marked this conversation as resolved.
Show resolved Hide resolved
},
"built_in": resourceSchema.BoolAttribute{
MarkdownDescription: "True If built in.",
Computed: true,
},
}
}

func (o TelemetryServiceRegistryEntry) DataSourceAttributes() map[string]dataSourceSchema.Attribute {
return map[string]dataSourceSchema.Attribute{
"service_name": dataSourceSchema.StringAttribute{
MarkdownDescription: "Service Name. Used to identify the Service.",
Required: true,
Validators: []validator.String{stringvalidator.LengthAtLeast(1)},
},
"application_schema": dataSourceSchema.StringAttribute{
MarkdownDescription: "Application Schema expressed in Json schema",
Computed: true,
},
"storage_schema_path": dataSourceSchema.StringAttribute{
MarkdownDescription: "Storage Schema Path",
Computed: true,
},
"description": dataSourceSchema.StringAttribute{
MarkdownDescription: "Description",
Computed: true,
},
"version": dataSourceSchema.StringAttribute{
MarkdownDescription: "Version",
Computed: true,
},
"built_in": dataSourceSchema.BoolAttribute{
MarkdownDescription: "True If built in.",
Computed: true,
},
}
}

func (o *TelemetryServiceRegistryEntry) LoadApiData(ctx context.Context, in *apstra.TelemetryServiceRegistryEntry, diag *diag.Diagnostics) {
o.ServiceName = types.StringValue(in.ServiceName)
o.Version = types.StringValue(in.Version)
o.Description = utils.StringValueOrNull(ctx, in.Description, diag)
o.Builtin = types.BoolValue(in.Builtin)
o.ApplicationSchema = types.StringValue(string(in.ApplicationSchema))
o.StorageSchemaPath = types.StringValue(in.StorageSchemaPath.String())
}

func (o *TelemetryServiceRegistryEntry) Request(ctx context.Context, d *diag.Diagnostics) *apstra.TelemetryServiceRegistryEntry {
rajagopalans marked this conversation as resolved.
Show resolved Hide resolved
var s apstra.StorageSchemaPath
e := s.FromString(o.StorageSchemaPath.ValueString())
if e != nil {
d.AddError("Failed to Parse Storage Schema Path", e.Error())
return nil
}
return &apstra.TelemetryServiceRegistryEntry{
ServiceName: o.ServiceName.ValueString(),
ApplicationSchema: []byte(o.ApplicationSchema.ValueString()),
StorageSchemaPath: s,
Builtin: o.Builtin.ValueBool(),
Description: o.Description.ValueString(),
Version: o.Version.ValueString(),
}
}
87 changes: 87 additions & 0 deletions apstra/data_source_telemetry_service_registry_entries.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package tfapstra

import (
"context"
"github.com/Juniper/apstra-go-sdk/apstra"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)

var _ datasource.DataSourceWithConfigure = &dataSourceTelemetryServiceRegistryEntries{}
var _ datasourceWithSetClient = &dataSourceTelemetryServiceRegistryEntries{}

type dataSourceTelemetryServiceRegistryEntries struct {
client *apstra.Client
}

func (o *dataSourceTelemetryServiceRegistryEntries) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_telemetry_service_registry_entries"
}

func (o *dataSourceTelemetryServiceRegistryEntries) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
configureDataSource(ctx, o, req, resp)
}

func (o *dataSourceTelemetryServiceRegistryEntries) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: docCategoryDesign + "This data source returns the Service Names of all Telemetry Service Registry Entries.",
Attributes: map[string]schema.Attribute{
"service_names": schema.SetAttribute{
MarkdownDescription: "A set of Apstra object ID numbers.",
rajagopalans marked this conversation as resolved.
Show resolved Hide resolved
Computed: true,
ElementType: types.StringType,
},
"built_in": schema.BoolAttribute{
MarkdownDescription: "Return only built_in if true, not built_in if false, all otherwise",
Optional: true,
},
},
}
}

func (o *dataSourceTelemetryServiceRegistryEntries) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var config struct {
ServiceNames types.Set `tfsdk:"service_names"`
BuiltIn types.Bool `tfsdk:"built_in"`
}

// get the configuration
resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
if resp.Diagnostics.HasError() {
return
}

var err error
rajagopalans marked this conversation as resolved.
Show resolved Hide resolved
tses, err := o.client.GetAllTelemetryServiceRegistryEntries(ctx)
if err != nil {
resp.Diagnostics.AddError("error retrieving Property Set IDs", err.Error())
rajagopalans marked this conversation as resolved.
Show resolved Hide resolved
return
}
var snames []string
for _, t := range tses {
if config.BuiltIn.IsUnknown() || config.BuiltIn.IsNull() || config.BuiltIn.ValueBool() == t.Builtin {
snames = append(snames, t.ServiceName)
}
}

snameSet, diags := types.SetValueFrom(ctx, types.StringType, snames)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

// create new state object
var state struct {
ServiceNames types.Set `tfsdk:"service_names"`
BuiltIn types.Bool `tfsdk:"built_in"`
}
state.ServiceNames = snameSet
state.BuiltIn = config.BuiltIn
// set state
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}

func (o *dataSourceTelemetryServiceRegistryEntries) setClient(client *apstra.Client) {
o.client = client
}
71 changes: 71 additions & 0 deletions apstra/data_source_telemetry_service_registry_entry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package tfapstra

import (
"context"
"fmt"
"github.com/Juniper/apstra-go-sdk/apstra"
"github.com/Juniper/terraform-provider-apstra/apstra/analytics"
"github.com/Juniper/terraform-provider-apstra/apstra/utils"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/path"
)

var _ datasource.DataSourceWithConfigure = &dataSourceTelemetryServiceRegistryEntry{}
var _ datasourceWithSetClient = &dataSourceTelemetryServiceRegistryEntry{}

type dataSourceTelemetryServiceRegistryEntry struct {
client *apstra.Client
}

func (o *dataSourceTelemetryServiceRegistryEntry) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_telemetry_service_registry_entry"
}

func (o *dataSourceTelemetryServiceRegistryEntry) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
configureDataSource(ctx, o, req, resp)
}

func (o *dataSourceTelemetryServiceRegistryEntry) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: docCategoryDesign + "This data source provides details of a specific TelemetryServiceRegistryEntry.\n\n" +
"At least one optional attribute is required.",
rajagopalans marked this conversation as resolved.
Show resolved Hide resolved
Attributes: analytics.TelemetryServiceRegistryEntry{}.DataSourceAttributes(),
}
}

func (o *dataSourceTelemetryServiceRegistryEntry) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var config analytics.TelemetryServiceRegistryEntry
resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
if resp.Diagnostics.HasError() {
return
}

var err error
var api *apstra.TelemetryServiceRegistryEntry
api, err = o.client.GetTelemetryServiceRegistryEntry(ctx, config.ServiceName.ValueString())
rajagopalans marked this conversation as resolved.
Show resolved Hide resolved
if utils.IsApstra404(err) {
resp.Diagnostics.AddAttributeError(
path.Root("name"),
"TelemetryServiceRegistryEntry not found",
fmt.Sprintf("TelemetryServiceRegistryEntry with Name %q not found", config.ServiceName.ValueString()))
return
}
if err != nil { // catch errors other than 404 from above
resp.Diagnostics.AddError("Error retrieving TelemetryServiceRegistryEntry", err.Error())
return
}

// create new state object
var state analytics.TelemetryServiceRegistryEntry
state.LoadApiData(ctx, api, &resp.Diagnostics)
if resp.Diagnostics.HasError() {
return
}
// Set state
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}

func (o *dataSourceTelemetryServiceRegistryEntry) setClient(client *apstra.Client) {
o.client = client
}
61 changes: 61 additions & 0 deletions apstra/data_source_telemetry_service_registry_entry_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package tfapstra

import (
"context"
"errors"
"fmt"
testutils "github.com/Juniper/terraform-provider-apstra/apstra/test_utils"
"github.com/Juniper/terraform-provider-apstra/apstra/utils"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"strings"
"testing"
)

const (
dataSourceTelemetryServiceRegistryByServiceNameHCL = `
data "apstra_telemetry_service_registry_entry" "test" {
service_name = "%s"
}
`
)

func TestAccDataSourceTelemetryServiceRegistryEntry(t *testing.T) {
ctx := context.Background()

ts := testutils.TelemetryServiceRegistryEntryA(t, ctx)

TestAppSchema := func(state string) error {
var diags diag.Diagnostics
if !utils.JSONEqual(types.StringValue(state), types.StringValue(string(ts.ApplicationSchema)), &diags) {
return fmt.Errorf("input schema does not match output Input %v. Output %v", ts.ApplicationSchema, state)
}
if diags.HasError() {
var sb strings.Builder
for _, d := range diags.Errors() {
sb.WriteString(d.Summary() + "\n")
sb.WriteString(d.Detail() + "\n")
}
return errors.New(sb.String())
}
return nil
}

resource.Test(t, resource.TestCase{
//PreCheck: setup,
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Read by ID
{
Config: insecureProviderConfigHCL + fmt.Sprintf(dataSourceTelemetryServiceRegistryByServiceNameHCL, ts.ServiceName),
Check: resource.ComposeAggregateTestCheckFunc(
// Verify data source/resource fields match
resource.TestCheckResourceAttr("data.apstra_telemetry_service_registry_entry.test", "service_name", ts.ServiceName),
resource.TestCheckResourceAttr("data.apstra_telemetry_service_registry_entry.test", "storage_schema_path", ts.StorageSchemaPath.String()),
resource.TestCheckResourceAttrWith("data.apstra_telemetry_service_registry_entry.test", "application_schema", TestAppSchema),
),
},
},
})
}
3 changes: 3 additions & 0 deletions apstra/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,8 @@ func (p *Provider) DataSources(_ context.Context) []func() datasource.DataSource
func() datasource.DataSource { return &dataSourceRackType{} },
func() datasource.DataSource { return &dataSourceRackTypes{} },
func() datasource.DataSource { return &dataSourceTag{} },
func() datasource.DataSource { return &dataSourceTelemetryServiceRegistryEntry{} },
func() datasource.DataSource { return &dataSourceTelemetryServiceRegistryEntries{} },
func() datasource.DataSource { return &dataSourceTemplateCollapsed{} },
func() datasource.DataSource { return &dataSourceTemplatePodBased{} },
func() datasource.DataSource { return &dataSourceTemplateRackBased{} },
Expand Down Expand Up @@ -563,6 +565,7 @@ func (p *Provider) Resources(_ context.Context) []func() resource.Resource {
func() resource.Resource { return &resourcePropertySet{} },
func() resource.Resource { return &resourceRackType{} },
func() resource.Resource { return &resourceTag{} },
func() resource.Resource { return &resourceTelemetryServiceRegistryEntry{} },
func() resource.Resource { return &resourceTemplateCollapsed{} },
func() resource.Resource { return &resourceTemplatePodBased{} },
func() resource.Resource { return &resourceTemplateRackBased{} },
Expand Down
Loading
Loading