Skip to content

Commit

Permalink
r/switch_options: use new provider via framework
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremmfr committed Dec 11, 2023
1 parent c8d88a6 commit 841c214
Show file tree
Hide file tree
Showing 9 changed files with 324 additions and 323 deletions.
7 changes: 7 additions & 0 deletions .changes/issue-575.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!-- markdownlint-disable-file MD013 MD041 -->
ENHANCEMENTS:

* **resource/junos_switch_options**:
* resource now use new [terraform-plugin-framework](https://github.com/hashicorp/terraform-plugin-framework)
optional boolean attributes doesn't accept value *false*
optional string attributes doesn't accept *empty* value
1 change: 1 addition & 0 deletions internal/providerfwk/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ func (p *junosProvider) Resources(_ context.Context) []func() resource.Resource
newServicesFlowMonitoringV9TemplateResource,
newServicesFlowMonitoringVIPFixTemplateResource,
newStaticRouteResource,
newSwitchOptionsResource,
newSystemResource,
}
}
Expand Down
270 changes: 270 additions & 0 deletions internal/providerfwk/resource_switch_options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
package providerfwk

import (
"context"
"strings"

"github.com/jeremmfr/terraform-provider-junos/internal/junos"
"github.com/jeremmfr/terraform-provider-junos/internal/tfvalidator"

"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"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"
balt "github.com/jeremmfr/go-utils/basicalter"
)

// Ensure the implementation satisfies the expected interfaces.
var (
_ resource.Resource = &switchOptions{}
_ resource.ResourceWithConfigure = &switchOptions{}
_ resource.ResourceWithImportState = &switchOptions{}
)

type switchOptions struct {
client *junos.Client
}

func newSwitchOptionsResource() resource.Resource {
return &switchOptions{}
}

func (rsc *switchOptions) typeName() string {
return providerName + "_switch_options"
}

func (rsc *switchOptions) junosName() string {
return "switch-options"
}

func (rsc *switchOptions) junosClient() *junos.Client {
return rsc.client
}

func (rsc *switchOptions) Metadata(
_ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse,
) {
resp.TypeName = rsc.typeName()
}

func (rsc *switchOptions) Configure(
ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse,
) {
// Prevent panic if the provider has not been configured.
if req.ProviderData == nil {
return
}
client, ok := req.ProviderData.(*junos.Client)
if !ok {
unexpectedResourceConfigureType(ctx, req, resp)

return
}
rsc.client = client
}

func (rsc *switchOptions) Schema(
_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse,
) {
resp.Schema = schema.Schema{
Description: "Configure static configuration in `" + rsc.junosName() + "` block",
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Computed: true,
Description: "An identifier for the resource with value `switch_options`.",
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"clean_on_destroy": schema.BoolAttribute{
Optional: true,
Description: "Clean supported lines when destroy this resource.",
Validators: []validator.Bool{
tfvalidator.BoolTrue(),
},
},
"vtep_source_interface": schema.StringAttribute{
Optional: true,
Description: "Source layer-3 IFL for VXLAN.",
Validators: []validator.String{
stringvalidator.LengthAtLeast(1),
tfvalidator.StringFormat(tfvalidator.InterfaceFormat),
tfvalidator.String1DotCount(),
},
},
},
}
}

type switchOptionsData struct {
CleanOnDestroy types.Bool `tfsdk:"clean_on_destroy"`
ID types.String `tfsdk:"id"`
VTEPSourceInterface types.String `tfsdk:"vtep_source_interface"`
}

func (rsc *switchOptions) Create(
ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse,
) {
var plan switchOptionsData
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
if resp.Diagnostics.HasError() {
return
}

defaultResourceCreate(
ctx,
rsc,
nil,
nil,
&plan,
resp,
)
}

func (rsc *switchOptions) Read(
ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse,
) {
var state, data switchOptionsData
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}

var _ resourceDataReadFrom0String = &data
defaultResourceRead(
ctx,
rsc,
nil,
&data,
func() {
data.CleanOnDestroy = state.CleanOnDestroy
},
resp,
)
}

func (rsc *switchOptions) Update(
ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse,
) {
var plan, state switchOptionsData
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}

defaultResourceUpdate(
ctx,
rsc,
&state,
&plan,
resp,
)
}

func (rsc *switchOptions) Delete(
ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse,
) {
var state switchOptionsData
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}

if state.CleanOnDestroy.ValueBool() {
defaultResourceDelete(
ctx,
rsc,
&state,
resp,
)
}
}

func (rsc *switchOptions) ImportState(
ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse,
) {
var data switchOptionsData

var _ resourceDataReadFrom0String = &data
defaultResourceImportState(
ctx,
rsc,
&data,
req,
resp,
"",
)
}

func (rscData *switchOptionsData) fillID() {
rscData.ID = types.StringValue("switch_options")
}

func (rscData *switchOptionsData) nullID() bool {
return rscData.ID.IsNull()
}

func (rscData *switchOptionsData) set(
_ context.Context, junSess *junos.Session,
) (
path.Path, error,
) {
configSet := make([]string, 0)
setPrefix := "set switch-options "

if v := rscData.VTEPSourceInterface.ValueString(); v != "" {
configSet = append(configSet, setPrefix+"vtep-source-interface "+v)
}

return path.Empty(), junSess.ConfigSet(configSet)
}

func (rscData *switchOptionsData) read(
_ context.Context, junSess *junos.Session,
) (
err error,
) {
showConfig, err := junSess.Command(junos.CmdShowConfig +
"switch-options" + junos.PipeDisplaySetRelative)
if err != nil {
return err
}
rscData.fillID()
if showConfig != junos.EmptyW {
for _, item := range strings.Split(showConfig, "\n") {
if strings.Contains(item, junos.XMLStartTagConfigOut) {
continue
}
if strings.Contains(item, junos.XMLEndTagConfigOut) {
break
}
itemTrim := strings.TrimPrefix(item, junos.SetLS)
if balt.CutPrefixInString(&itemTrim, "vtep-source-interface ") {
rscData.VTEPSourceInterface = types.StringValue(itemTrim)
}
}
}

return nil
}

func (rscData *switchOptionsData) del(
_ context.Context, junSess *junos.Session,
) error {
listLinesToDelete := []string{
"vtep-source-interface",
}

configSet := make([]string, len(listLinesToDelete))
delPrefix := "delete switch-options "
for i, line := range listLinesToDelete {
configSet[i] = delPrefix + line
}

return junSess.ConfigSet(configSet)
}
31 changes: 31 additions & 0 deletions internal/providerfwk/resource_switch_options_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package providerfwk_test

import (
"os"
"testing"

"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

func TestAccResourceSwitchOptions_basic(t *testing.T) {
if os.Getenv("TESTACC_ROUTER") != "" {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV5ProviderFactories: testAccProtoV5ProviderFactories,
Steps: []resource.TestStep{
{
ConfigDirectory: config.TestStepDirectory(),
},
{
ResourceName: "junos_switch_options.testacc_switchOpts",
ImportState: true,
ImportStateVerify: true,
},
{
ConfigDirectory: config.TestStepDirectory(),
},
},
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
resource "junos_interface_logical" "testacc_switchOpts" {
lifecycle {
create_before_destroy = true
}
name = "lo0.0"
family_inet {
address {
cidr_ip = "192.0.2.16/32"
}
}
}
resource "junos_switch_options" "testacc_switchOpts" {
vtep_source_interface = junos_interface_logical.testacc_switchOpts.name
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
resource "junos_switch_options" "testacc_switchOpts" {}
1 change: 0 additions & 1 deletion internal/providersdk/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ func Provider() *schema.Provider {
"junos_snmp_v3_vacm_accessgroup": resourceSnmpV3VacmAccessGroup(),
"junos_snmp_v3_vacm_securitytogroup": resourceSnmpV3VacmSecurityToGroup(),
"junos_snmp_view": resourceSnmpView(),
"junos_switch_options": resourceSwitchOptions(),
"junos_system_login_class": resourceSystemLoginClass(),
"junos_system_login_user": resourceSystemLoginUser(),
"junos_system_ntp_server": resourceSystemNtpServer(),
Expand Down
Loading

0 comments on commit 841c214

Please sign in to comment.