From 111100a39af8749ed4e350f54d3cf12063302467 Mon Sep 17 00:00:00 2001 From: Dawoud Date: Thu, 30 Mar 2023 16:40:59 -0700 Subject: [PATCH 1/9] Add interface_wireguard client code --- .github/workflows/continuous-integration.yml | 3 + client/helpers.go | 13 +++ client/interface_wireguard.go | 89 ++++++++++++++++++++ client/interface_wireguard_test.go | 69 +++++++++++++++ 4 files changed, 174 insertions(+) create mode 100644 client/interface_wireguard.go create mode 100644 client/interface_wireguard_test.go diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 981b30cf..fbb42030 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -19,12 +19,15 @@ jobs: # Test against latest stable release, v6 beta and v7 beta routeros: ["6.48.3", "6.49beta54"] legacy_bgp_support: [true] + interface_wireguard_support: [false] include: - experimental: true go: 1.18 os: ubuntu-latest routeros: "latest" legacy_bgp_support: false + interface_wireguard_support: true + steps: - name: Set up Go uses: actions/setup-go@v1 diff --git a/client/helpers.go b/client/helpers.go index 1fa53783..73881b15 100644 --- a/client/helpers.go +++ b/client/helpers.go @@ -17,3 +17,16 @@ func IsLegacyBgpSupported() bool { } return false } + +func SkipInterfaceWireguardIfUnsupported(t *testing.T) { + if !IsInterfaceWireguardSupported() { + t.Skip() + } +} + +func IsInterfaceWireguardSupported() bool { + if os.Getenv("INTERFACE_WIREGUARD_SUPPORT") == "true" { + return true + } + return false +} diff --git a/client/interface_wireguard.go b/client/interface_wireguard.go new file mode 100644 index 00000000..3836080a --- /dev/null +++ b/client/interface_wireguard.go @@ -0,0 +1,89 @@ +package client + +import ( + "github.com/go-routeros/routeros" +) + +type InterfaceWireguard struct { + Name string `mikrotik:"name"` + Comment string `mikrotik:"comment"` + Disabled bool `mikrotik:"disabled"` + ListenPort int `mikrotik:"listen-port"` + Mtu int `mikrotik:"mtu"` + PrivateKey string `mikrotik:"private-key"` + PublicKey string `mikrotik:"public-key"` //read only property + Running bool `mikrotik:"running"` //read only property +} + +func (i *InterfaceWireguard) ActionToCommand(action Action) string { + return map[Action]string{ + Add: "/interface/wireguard/add", + Find: "/interface/wireguard/print", + List: "/interface/wireguard/print", + Update: "/interface/wireguard/set", + Delete: "/interface/wireguard/remove", + }[action] +} + +func (i *InterfaceWireguard) IDField() string { + return "name" +} + +func (i *InterfaceWireguard) ID() string { + return i.Name +} + +func (i *InterfaceWireguard) SetID(id string) { + i.Name = id +} + +func (i *InterfaceWireguard) AfterAddHook(r *routeros.Reply) { + i.Name = r.Done.Map["ret"] +} + +func (i *InterfaceWireguard) FindField() string { + return "name" +} + +func (i *InterfaceWireguard) FindFieldValue() string { + return i.Name +} + +func (i *InterfaceWireguard) DeleteField() string { + return "name" +} + +func (i *InterfaceWireguard) DeleteFieldValue() string { + return i.Name +} + +func (client Mikrotik) AddInterfaceWireguard(i *InterfaceWireguard) (*InterfaceWireguard, error) { + res, err := client.Add(i) + if err != nil { + return nil, err + } + + return res.(*InterfaceWireguard), nil +} + +func (client Mikrotik) FindInterfaceWireguard(name string) (*InterfaceWireguard, error) { + res, err := client.Find(&InterfaceWireguard{Name: name}) + if err != nil { + return nil, err + } + + return res.(*InterfaceWireguard), nil +} + +func (client Mikrotik) UpdateInterfaceWireguard(i *InterfaceWireguard) (*InterfaceWireguard, error) { + res, err := client.Update(i) + if err != nil { + return nil, err + } + + return res.(*InterfaceWireguard), nil +} + +func (client Mikrotik) DeleteInterfaceWireguard(name string) error { + return client.Delete(&InterfaceWireguard{Name: name}) +} diff --git a/client/interface_wireguard_test.go b/client/interface_wireguard_test.go new file mode 100644 index 00000000..72fba0c7 --- /dev/null +++ b/client/interface_wireguard_test.go @@ -0,0 +1,69 @@ +package client + +import ( + "errors" + "reflect" + "testing" +) + +func TestFindInterfaceWireguard_onNonExistantInterfaceWireguard(t *testing.T) { + c := NewClient(GetConfigFromEnv()) + + name := "Interface wireguard does not exist" + _, err := c.FindInterfaceWireguard(name) + + if _, ok := err.(*NotFound); !ok { + t.Errorf("Expecting to receive NotFound error for Interface wireguard `%s`, instead error was nil.", name) + } +} + +func TestAddFindDeleteInterfaceWireguard(t *testing.T) { + c := NewClient(GetConfigFromEnv()) + + name := "new_interface_wireguard" + interfaceWireguard := &InterfaceWireguard{ + Name: name, + Disabled: false, + ListenPort: 10000, + Mtu: 10001, + PrivateKey: "YOi0P0lTTiN8hAQvuRET23Srb+U7C52iOZokj0CCSkM=", + Comment: "new interface from test", + } + + created, err := c.Add(interfaceWireguard) + if err != nil { + t.Errorf("expected no error, got %v", err) + return + } + + findInterface := &InterfaceWireguard{} + findInterface.Name = name + found, err := c.Find(findInterface) + if err != nil { + t.Errorf("expected no error, got %v", err) + return + } + + if _, ok := found.(Resource); !ok { + t.Error("expected found resource to implement Resource interface, but it doesn't") + return + } + if !reflect.DeepEqual(created, found) { + t.Error("expected created and found resources to be equal, but they don't") + } + err = c.Delete(found.(Resource)) + if err != nil { + t.Errorf("expected no error, got %v", err) + } + + _, err = c.Find(findInterface) + if err == nil { + t.Errorf("expected error, got nothing") + return + } + + target := &NotFound{} + if !errors.As(err, &target) { + t.Errorf("expected error to be of type %T, got %T", &NotFound{}, err) + } +} From c983b900c03988abb6e481623e48d9a9a17ce738 Mon Sep 17 00:00:00 2001 From: Dawoud Date: Thu, 30 Mar 2023 16:59:05 -0700 Subject: [PATCH 2/9] Add provider side code --- .github/workflows/continuous-integration.yml | 2 + .gitignore | 1 + client/interface_wireguard.go | 15 +- client/interface_wireguard_test.go | 2 + go.mod | 5 +- go.sum | 6 + mikrotik/provider_framework.go | 1 + mikrotik/resource_interface_wireguard.go | 242 ++++++++++++++++++ mikrotik/resource_interface_wireguard_test.go | 173 +++++++++++++ 9 files changed, 438 insertions(+), 9 deletions(-) create mode 100644 mikrotik/resource_interface_wireguard.go create mode 100644 mikrotik/resource_interface_wireguard_test.go diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index fbb42030..25a51c48 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -55,6 +55,7 @@ jobs: MIKROTIK_PASSWORD: '' TF_ACC: 1 LEGACY_BGP_SUPPORT: ${{ matrix.legacy_bgp_support }} + INTERFACE_WIREGUARD_SUPPORT: ${{ matrix.interface_wireguard_support }} - name: Run client tests run: make testclient @@ -64,6 +65,7 @@ jobs: MIKROTIK_PASSWORD: '' TF_ACC: 1 LEGACY_BGP_SUPPORT: ${{ matrix.legacy_bgp_support }} + INTERFACE_WIREGUARD_SUPPORT: ${{ matrix.interface_wireguard_support }} services: routeros: diff --git a/.gitignore b/.gitignore index bf0227cb..bcd2dcf8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ terraform-provider-mikrotik dist/ vendor +go.work.sum \ No newline at end of file diff --git a/client/interface_wireguard.go b/client/interface_wireguard.go index 3836080a..1224e80f 100644 --- a/client/interface_wireguard.go +++ b/client/interface_wireguard.go @@ -5,14 +5,15 @@ import ( ) type InterfaceWireguard struct { + Id string `mikrotik:".id"` Name string `mikrotik:"name"` Comment string `mikrotik:"comment"` Disabled bool `mikrotik:"disabled"` ListenPort int `mikrotik:"listen-port"` Mtu int `mikrotik:"mtu"` PrivateKey string `mikrotik:"private-key"` - PublicKey string `mikrotik:"public-key"` //read only property - Running bool `mikrotik:"running"` //read only property + PublicKey string `mikrotik:"public-key"` //read only property + Running bool `mikrotik:"running,readonly"` //read only property } func (i *InterfaceWireguard) ActionToCommand(action Action) string { @@ -26,19 +27,19 @@ func (i *InterfaceWireguard) ActionToCommand(action Action) string { } func (i *InterfaceWireguard) IDField() string { - return "name" + return ".id" } func (i *InterfaceWireguard) ID() string { - return i.Name + return i.Id } func (i *InterfaceWireguard) SetID(id string) { - i.Name = id + i.Id = id } func (i *InterfaceWireguard) AfterAddHook(r *routeros.Reply) { - i.Name = r.Done.Map["ret"] + i.Id = r.Done.Map["ret"] } func (i *InterfaceWireguard) FindField() string { @@ -50,7 +51,7 @@ func (i *InterfaceWireguard) FindFieldValue() string { } func (i *InterfaceWireguard) DeleteField() string { - return "name" + return "numbers" } func (i *InterfaceWireguard) DeleteFieldValue() string { diff --git a/client/interface_wireguard_test.go b/client/interface_wireguard_test.go index 72fba0c7..1dc64596 100644 --- a/client/interface_wireguard_test.go +++ b/client/interface_wireguard_test.go @@ -7,6 +7,7 @@ import ( ) func TestFindInterfaceWireguard_onNonExistantInterfaceWireguard(t *testing.T) { + SkipInterfaceWireguardIfUnsupported(t) c := NewClient(GetConfigFromEnv()) name := "Interface wireguard does not exist" @@ -18,6 +19,7 @@ func TestFindInterfaceWireguard_onNonExistantInterfaceWireguard(t *testing.T) { } func TestAddFindDeleteInterfaceWireguard(t *testing.T) { + SkipInterfaceWireguardIfUnsupported(t) c := NewClient(GetConfigFromEnv()) name := "new_interface_wireguard" diff --git a/go.mod b/go.mod index 70f786a2..6db26f82 100644 --- a/go.mod +++ b/go.mod @@ -41,6 +41,7 @@ require ( github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/terraform-exec v0.17.2 // indirect github.com/hashicorp/terraform-json v0.14.0 // indirect + github.com/hashicorp/terraform-plugin-framework-validators v0.10.0 // indirect github.com/hashicorp/terraform-plugin-log v0.8.0 // indirect github.com/hashicorp/terraform-registry-address v0.1.0 // indirect github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect @@ -63,13 +64,13 @@ require ( github.com/spf13/cast v1.5.0 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect - github.com/vmihailenco/tagparser v0.1.1 // indirect + github.com/vmihailenco/tagparser v0.1.2 // indirect github.com/zclconf/go-cty v1.10.0 // indirect golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect golang.org/x/text v0.4.0 // indirect - google.golang.org/appengine v1.6.6 // indirect + google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20200711021454-869866162049 // indirect google.golang.org/grpc v1.51.0 // indirect google.golang.org/protobuf v1.28.1 // indirect diff --git a/go.sum b/go.sum index 9af52823..746c7e7f 100644 --- a/go.sum +++ b/go.sum @@ -126,6 +126,8 @@ github.com/hashicorp/terraform-plugin-docs v0.13.0 h1:6e+VIWsVGb6jYJewfzq2ok2smP github.com/hashicorp/terraform-plugin-docs v0.13.0/go.mod h1:W0oCmHAjIlTHBbvtppWHe8fLfZ2BznQbuv8+UD8OucQ= github.com/hashicorp/terraform-plugin-framework v1.2.0 h1:MZjFFfULnFq8fh04FqrKPcJ/nGpHOvX4buIygT3MSNY= github.com/hashicorp/terraform-plugin-framework v1.2.0/go.mod h1:nToI62JylqXDq84weLJ/U3umUsBhZAaTmU0HXIVUOcw= +github.com/hashicorp/terraform-plugin-framework-validators v0.10.0 h1:4L0tmy/8esP6OcvocVymw52lY0HyQ5OxB7VNl7k4bS0= +github.com/hashicorp/terraform-plugin-framework-validators v0.10.0/go.mod h1:qdQJCdimB9JeX2YwOpItEu+IrfoJjWQ5PhLpAOMDQAE= github.com/hashicorp/terraform-plugin-go v0.14.3 h1:nlnJ1GXKdMwsC8g1Nh05tK2wsC3+3BL/DBBxFEki+j0= github.com/hashicorp/terraform-plugin-go v0.14.3/go.mod h1:7ees7DMZ263q8wQ6E4RdIdR6nHHJtrdt4ogX5lPkX1A= github.com/hashicorp/terraform-plugin-log v0.8.0 h1:pX2VQ/TGKu+UU1rCay0OlzosNKe4Nz1pepLXj95oyy0= @@ -232,6 +234,8 @@ github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvC github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc= +github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= @@ -311,6 +315,8 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= diff --git a/mikrotik/provider_framework.go b/mikrotik/provider_framework.go index 8b5d3fef..0d0f88ac 100644 --- a/mikrotik/provider_framework.go +++ b/mikrotik/provider_framework.go @@ -183,6 +183,7 @@ func (p *ProviderFramework) DataSources(ctx context.Context) []func() datasource func (p *ProviderFramework) Resources(ctx context.Context) []func() resource.Resource { return []func() resource.Resource{ NewSchedulerResource, + NewInterfaceWireguardResource, } } diff --git a/mikrotik/resource_interface_wireguard.go b/mikrotik/resource_interface_wireguard.go new file mode 100644 index 00000000..258f41ba --- /dev/null +++ b/mikrotik/resource_interface_wireguard.go @@ -0,0 +1,242 @@ +package mikrotik + +import ( + "context" + "fmt" + + "github.com/ddelnano/terraform-provider-mikrotik/client" + "github.com/hashicorp/terraform-plugin-framework/diag" + "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/booldefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + tftypes "github.com/hashicorp/terraform-plugin-framework/types" +) + +type interfaceWireguard struct { + client *client.Mikrotik +} + +// Ensure the implementation satisfies the expected interfaces. +var ( + _ resource.Resource = &interfaceWireguard{} + _ resource.ResourceWithConfigure = &interfaceWireguard{} + _ resource.ResourceWithImportState = &interfaceWireguard{} +) + +// NewInterfaceWireguardResource is a helper function to simplify the provider implementation. +func NewInterfaceWireguardResource() resource.Resource { + return &interfaceWireguard{} + +} + +func (i *interfaceWireguard) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + i.client = req.ProviderData.(*client.Mikrotik) +} + +// Metadata returns the resource type name. +func (i *interfaceWireguard) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_interface_wireguard" +} + +// Schema defines the schema for the resource. +func (i *interfaceWireguard) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Creates a Mikrotik interface wireguard.", + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + Description: "Identifier of this resource assigned by RouterOS", + }, + "name": schema.StringAttribute{ + Required: true, + Description: "Name of the interface wireguard.", + }, + "comment": schema.StringAttribute{ + Optional: true, + Description: "Comment associated with interface wireguard.", + }, + "disabled": schema.BoolAttribute{ + Optional: true, + Computed: true, + Default: booldefault.StaticBool(false), + Description: "Boolean for whether or not the interface wireguard is disabled.", + }, + "listen_port": schema.Int64Attribute{ + Optional: true, + Computed: true, + Default: int64default.StaticInt64(13231), + Description: "Port for WireGuard service to listen on for incoming sessions.", + }, + "mtu": schema.Int64Attribute{ + Optional: true, + Computed: true, + Default: int64default.StaticInt64(1420), + Description: "Layer3 Maximum transmission unit.", + }, + "private_key": schema.StringAttribute{ + Optional: true, + Computed: true, + Description: "A base64 private key. If not specified, it will be automatically generated upon interface creation.", + }, + "public_key": schema.StringAttribute{ + Optional: false, + Computed: true, + Description: "", + }, + "running": schema.BoolAttribute{ + Optional: false, + Computed: true, + Description: "", + }, + }, + } +} + +// Create creates the resource and sets the initial Terraform state. +func (i *interfaceWireguard) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var plan interfaceWireguardModel + diags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + created, err := i.client.AddInterfaceWireguard(modelToInterfaceWireguard(&plan)) + if err != nil { + resp.Diagnostics.AddError("creation failed", err.Error()) + return + } + + resp.Diagnostics.Append(interfaceWireguardToModel(created, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } +} + +// Read refreshes the Terraform state with the latest data. +func (i *interfaceWireguard) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state interfaceWireguardModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + resource, err := i.client.FindInterfaceWireguard(state.Name.ValueString()) + if err != nil { + resp.Diagnostics.AddError( + "Error reading remote resource", + fmt.Sprintf("Could not read interfaceWireguard with name %q", state.Name.ValueString()), + ) + return + } + + resp.Diagnostics.Append(interfaceWireguardToModel(resource, &state)...) + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } +} + +// Update updates the resource and sets the updated Terraform state on success. +func (i *interfaceWireguard) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan interfaceWireguardModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + updated, err := i.client.UpdateInterfaceWireguard(modelToInterfaceWireguard(&plan)) + if err != nil { + resp.Diagnostics.AddError("update failed", err.Error()) + return + } + + resp.Diagnostics.Append(interfaceWireguardToModel(updated, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } +} + +// Delete deletes the resource and removes the Terraform state on success. +func (i *interfaceWireguard) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state interfaceWireguardModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + if err := i.client.DeleteInterfaceWireguard(state.Name.ValueString()); err != nil { + resp.Diagnostics.AddError("Could not delete interfaceWireguard", err.Error()) + return + } +} + +func (i *interfaceWireguard) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + // Retrieve import ID and save to id attribute + resource.ImportStatePassthroughID(ctx, path.Root("name"), req, resp) +} + +type interfaceWireguardModel struct { + ID tftypes.String `tfsdk:"id"` + Name tftypes.String `tfsdk:"name"` + Comment tftypes.String `tfsdk:"comment"` + Disabled tftypes.Bool `tfsdk:"disabled"` + ListenPort tftypes.Int64 `tfsdk:"listen_port"` + Mtu tftypes.Int64 `tfsdk:"mtu"` + PrivateKey tftypes.String `tfsdk:"private_key"` + PublicKey tftypes.String `tfsdk:"public_key"` + Running tftypes.Bool `tfsdk:"running"` +} + +func interfaceWireguardToModel(i *client.InterfaceWireguard, m *interfaceWireguardModel) diag.Diagnostics { + var diags diag.Diagnostics + if i == nil { + diags.AddError("Interface Wireguard cannot be nil", "Cannot build model from nil object") + return diags + } + m.ID = tftypes.StringValue(i.Id) + m.Name = tftypes.StringValue(i.Name) + m.Comment = tftypes.StringValue(i.Comment) + m.Disabled = tftypes.BoolValue(i.Disabled) + m.ListenPort = tftypes.Int64Value(int64(i.ListenPort)) + m.Mtu = tftypes.Int64Value(int64(i.Mtu)) + m.PrivateKey = tftypes.StringValue(i.PrivateKey) + m.PublicKey = tftypes.StringValue(i.PublicKey) + m.Running = tftypes.BoolValue(i.Running) + + return diags +} + +func modelToInterfaceWireguard(m *interfaceWireguardModel) *client.InterfaceWireguard { + return &client.InterfaceWireguard{ + Id: m.ID.ValueString(), + Name: m.Name.ValueString(), + Comment: m.Comment.ValueString(), + Disabled: m.Disabled.ValueBool(), + ListenPort: int(m.ListenPort.ValueInt64()), + Mtu: int(m.Mtu.ValueInt64()), + PrivateKey: m.PrivateKey.ValueString(), + PublicKey: m.PublicKey.ValueString(), + Running: m.Running.ValueBool(), + } +} diff --git a/mikrotik/resource_interface_wireguard_test.go b/mikrotik/resource_interface_wireguard_test.go new file mode 100644 index 00000000..6fc32bed --- /dev/null +++ b/mikrotik/resource_interface_wireguard_test.go @@ -0,0 +1,173 @@ +package mikrotik + +import ( + "fmt" + "strconv" + "testing" + + "github.com/ddelnano/terraform-provider-mikrotik/client" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +var origComment string = "testing" +var origListenPort int = 13231 +var origMTU int = 1420 +var updatedComment string = "new_comment" + +func TestAccMikrotikInterfaceWireguard_create(t *testing.T) { + client.SkipInterfaceWireguardIfUnsupported(t) + name := acctest.RandomWithPrefix("tf-acc-create") + + resourceName := "mikrotik_interface_wireguard.bar" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV5ProviderFactories: testAccProtoV5ProviderFactories, + CheckDestroy: testAccCheckMikrotikInterfaceWireguardDestroy, + Steps: []resource.TestStep{ + { + Config: testAccInterfaceWireguard(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccInterfaceWireguardExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "name", name), + resource.TestCheckResourceAttr(resourceName, "comment", origComment), + resource.TestCheckResourceAttr(resourceName, "listen_port", strconv.Itoa(origListenPort)), + resource.TestCheckResourceAttr(resourceName, "mtu", strconv.Itoa(origMTU)), + resource.TestCheckResourceAttr(resourceName, "disabled", "false")), + }, + }, + }) +} + +func TestAccMikrotikInterfaceWireguard_updatedComment(t *testing.T) { + client.SkipInterfaceWireguardIfUnsupported(t) + name := acctest.RandomWithPrefix("tf-acc-update-comment") + + resourceName := "mikrotik_interface_wireguard.bar" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV5ProviderFactories: testAccProtoV5ProviderFactories, + CheckDestroy: testAccCheckMikrotikInterfaceWireguardDestroy, + Steps: []resource.TestStep{ + { + Config: testAccInterfaceWireguard(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccInterfaceWireguardExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "name", name), + resource.TestCheckResourceAttr(resourceName, "comment", origComment)), + }, + { + Config: testAccInterfaceWireguardUpdatedComment(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccInterfaceWireguardExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "name", name), + resource.TestCheckResourceAttr(resourceName, "comment", updatedComment)), + }, + }, + }) +} + +func TestAccMikrotikInterfaceWireguard_import(t *testing.T) { + client.SkipInterfaceWireguardIfUnsupported(t) + name := acctest.RandomWithPrefix("tf-acc-import") + + resourceName := "mikrotik_interface_wireguard.bar" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV5ProviderFactories: testAccProtoV5ProviderFactories, + CheckDestroy: testAccCheckMikrotikInterfaceWireguardDestroy, + Steps: []resource.TestStep{ + { + Config: testAccInterfaceWireguard(name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccInterfaceWireguardExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "id"), + resource.TestCheckResourceAttrSet(resourceName, "name"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: func(s *terraform.State) (string, error) { + return name, nil + }, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccInterfaceWireguard(name string) string { + return fmt.Sprintf(` +resource "mikrotik_interface_wireguard" "bar" { + name = "%s" + comment = "%s" + listen_port = "%d" + mtu = "%d" +} +`, name, origComment, origListenPort, origMTU) +} + +func testAccInterfaceWireguardUpdatedComment(name string) string { + return fmt.Sprintf(` + resource "mikrotik_interface_wireguard" "bar" { + name = "%s" + comment = "%s" + listen_port = "%d" + mtu = "%d" + } + `, name, updatedComment, origListenPort, origMTU) +} + +func testAccCheckMikrotikInterfaceWireguardDestroy(s *terraform.State) error { + c := client.NewClient(client.GetConfigFromEnv()) + for _, rs := range s.RootModule().Resources { + if rs.Type != "mikrotik_interface_wireguard" { + continue + } + + interfaceWireguard, err := c.FindInterfaceWireguard(rs.Primary.Attributes["name"]) + + _, ok := err.(*client.NotFound) + if !ok && err != nil { + return err + } + + if interfaceWireguard != nil { + return fmt.Errorf("interface wireguard (%s) still exists", interfaceWireguard.Name) + } + } + return nil +} + +func testAccInterfaceWireguardExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("mikrotik_interface_wireguard does not exist in the statefile") + } + + c := client.NewClient(client.GetConfigFromEnv()) + + interfaceWireguard, err := c.FindInterfaceWireguard(rs.Primary.Attributes["name"]) + + _, ok = err.(*client.NotFound) + if !ok && err != nil { + return fmt.Errorf("Unable to get the interface wireguard with error: %v", err) + } + + if interfaceWireguard == nil { + return fmt.Errorf("Unable to get the interface wireguard with name: %s", rs.Primary.Attributes["name"]) + } + + if interfaceWireguard.Name == rs.Primary.Attributes["name"] { + return nil + } + return nil + } +} From f1968e1c74c6f6238eb22471e6da541dc39fb6ce Mon Sep 17 00:00:00 2001 From: Dawoud Date: Wed, 10 May 2023 16:18:50 -0700 Subject: [PATCH 3/9] Add markdown file --- docs/resources/interface_wireguard.md | 0 mikrotik/resource_interface_wireguard.go | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 docs/resources/interface_wireguard.md diff --git a/docs/resources/interface_wireguard.md b/docs/resources/interface_wireguard.md new file mode 100644 index 00000000..e69de29b diff --git a/mikrotik/resource_interface_wireguard.go b/mikrotik/resource_interface_wireguard.go index 258f41ba..15e43800 100644 --- a/mikrotik/resource_interface_wireguard.go +++ b/mikrotik/resource_interface_wireguard.go @@ -92,12 +92,12 @@ func (i *interfaceWireguard) Schema(_ context.Context, _ resource.SchemaRequest, "public_key": schema.StringAttribute{ Optional: false, Computed: true, - Description: "", + Description: "A base64 public key is calculated from the private key.", }, "running": schema.BoolAttribute{ Optional: false, Computed: true, - Description: "", + Description: "Whether the interface is running.", }, }, } From e9e399416ab87abef9d9436cec2e22701e6bd144 Mon Sep 17 00:00:00 2001 From: Dawoud Date: Wed, 10 May 2023 16:23:58 -0700 Subject: [PATCH 4/9] Edit markdown file --- docs/resources/interface_wireguard.md | 38 +++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/resources/interface_wireguard.md b/docs/resources/interface_wireguard.md index e69de29b..444ac06b 100644 --- a/docs/resources/interface_wireguard.md +++ b/docs/resources/interface_wireguard.md @@ -0,0 +1,38 @@ +# mikrotik_interface_wireguard (Resource) +Creates a Mikrotik interface_wireguard. + +## Example Usage +```terraform +resource "mikrotik_interface_wireguard" "interface_wireguard" { + name = "interface_wireguard-name" +} +``` + + +## Schema + +### Required + +- `name` (String) Name of the tunnel. + +### Optional + +- `comment` (String) Short description of the tunnel. +- `disabled` (Boolean) Enables/disables the tunnel. Default: `false` +- `listen_port` (Number) Port for WireGuard service to listen on for incoming sessions. Default: `13231` +- `mtu` (Number) Layer3 Maximum transmission unit. Default: `1420` +- `private_key` (String) A base64 private key. If not specified, it will be automatically generated upon interface creation. +- + + +### Read-Only + +- `id` (String) The ID of this resource. +- `public_key` (String) A base64 public key is calculated from the private key. +- `running` (Boolean) Whether the interface is running. + +## Import +Import is supported using the following syntax: +```shell +terraform import mikrotik_interface_wireguard.interface_wireguard interface_wireguard-name +``` From 9e8abdc1197a6dc1d7e0b0923fd8a576502228a9 Mon Sep 17 00:00:00 2001 From: Dawoud Date: Fri, 12 May 2023 12:29:48 -0700 Subject: [PATCH 5/9] Fix first round of review comments --- client/interface_wireguard.go | 4 ++-- client/interface_wireguard_test.go | 28 +++++++++++++----------- go.work.sum | 1 + mikrotik/resource_interface_wireguard.go | 14 ++++++++---- 4 files changed, 28 insertions(+), 19 deletions(-) create mode 100644 go.work.sum diff --git a/client/interface_wireguard.go b/client/interface_wireguard.go index 1224e80f..1ec701b0 100644 --- a/client/interface_wireguard.go +++ b/client/interface_wireguard.go @@ -12,8 +12,8 @@ type InterfaceWireguard struct { ListenPort int `mikrotik:"listen-port"` Mtu int `mikrotik:"mtu"` PrivateKey string `mikrotik:"private-key"` - PublicKey string `mikrotik:"public-key"` //read only property - Running bool `mikrotik:"running,readonly"` //read only property + PublicKey string `mikrotik:"public-key,readonly"` //read only property + Running bool `mikrotik:"running,readonly"` //read only property } func (i *InterfaceWireguard) ActionToCommand(action Action) string { diff --git a/client/interface_wireguard_test.go b/client/interface_wireguard_test.go index 1dc64596..618dec54 100644 --- a/client/interface_wireguard_test.go +++ b/client/interface_wireguard_test.go @@ -53,19 +53,21 @@ func TestAddFindDeleteInterfaceWireguard(t *testing.T) { if !reflect.DeepEqual(created, found) { t.Error("expected created and found resources to be equal, but they don't") } - err = c.Delete(found.(Resource)) - if err != nil { - t.Errorf("expected no error, got %v", err) - } + defer func() { + err = c.Delete(found.(Resource)) + if err != nil { + t.Errorf("expected no error, got %v", err) + } - _, err = c.Find(findInterface) - if err == nil { - t.Errorf("expected error, got nothing") - return - } + _, err = c.Find(findInterface) + if err == nil { + t.Errorf("expected error, got nothing") + return + } - target := &NotFound{} - if !errors.As(err, &target) { - t.Errorf("expected error to be of type %T, got %T", &NotFound{}, err) - } + target := &NotFound{} + if !errors.As(err, &target) { + t.Errorf("expected error to be of type %T, got %T", &NotFound{}, err) + } + }() } diff --git a/go.work.sum b/go.work.sum new file mode 100644 index 00000000..56f9d847 --- /dev/null +++ b/go.work.sum @@ -0,0 +1 @@ +github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= diff --git a/mikrotik/resource_interface_wireguard.go b/mikrotik/resource_interface_wireguard.go index 15e43800..b51d51c3 100644 --- a/mikrotik/resource_interface_wireguard.go +++ b/mikrotik/resource_interface_wireguard.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/ddelnano/terraform-provider-mikrotik/client" + "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -13,6 +14,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" "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" tftypes "github.com/hashicorp/terraform-plugin-framework/types" ) @@ -49,7 +51,7 @@ func (i *interfaceWireguard) Metadata(_ context.Context, req resource.MetadataRe // Schema defines the schema for the resource. func (i *interfaceWireguard) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ - Description: "Creates a Mikrotik interface wireguard.", + Description: "Creates a Mikrotik interface wireguard only supported by RouterOS v7+.", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ Computed: true, @@ -79,14 +81,18 @@ func (i *interfaceWireguard) Schema(_ context.Context, _ resource.SchemaRequest, Description: "Port for WireGuard service to listen on for incoming sessions.", }, "mtu": schema.Int64Attribute{ - Optional: true, - Computed: true, - Default: int64default.StaticInt64(1420), + Optional: true, + Computed: true, + Default: int64default.StaticInt64(1420), + Validators: []validator.Int64{ + int64validator.Between(0, 65536), + }, Description: "Layer3 Maximum transmission unit.", }, "private_key": schema.StringAttribute{ Optional: true, Computed: true, + Sensitive: true, Description: "A base64 private key. If not specified, it will be automatically generated upon interface creation.", }, "public_key": schema.StringAttribute{ From 7efe088c463d97eb29a4f4dd3e8d1f81cecae01b Mon Sep 17 00:00:00 2001 From: Dawoud Date: Wed, 17 May 2023 17:12:15 -0700 Subject: [PATCH 6/9] Correct defer() placement --- client/interface_wireguard_test.go | 31 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/client/interface_wireguard_test.go b/client/interface_wireguard_test.go index 618dec54..6fb63f37 100644 --- a/client/interface_wireguard_test.go +++ b/client/interface_wireguard_test.go @@ -37,23 +37,22 @@ func TestAddFindDeleteInterfaceWireguard(t *testing.T) { t.Errorf("expected no error, got %v", err) return } - - findInterface := &InterfaceWireguard{} - findInterface.Name = name - found, err := c.Find(findInterface) - if err != nil { - t.Errorf("expected no error, got %v", err) - return - } - - if _, ok := found.(Resource); !ok { - t.Error("expected found resource to implement Resource interface, but it doesn't") - return - } - if !reflect.DeepEqual(created, found) { - t.Error("expected created and found resources to be equal, but they don't") - } defer func() { + findInterface := &InterfaceWireguard{} + findInterface.Name = name + found, err := c.Find(findInterface) + if err != nil { + t.Errorf("expected no error, got %v", err) + return + } + + if _, ok := found.(Resource); !ok { + t.Error("expected found resource to implement Resource interface, but it doesn't") + return + } + if !reflect.DeepEqual(created, found) { + t.Error("expected created and found resources to be equal, but they don't") + } err = c.Delete(found.(Resource)) if err != nil { t.Errorf("expected no error, got %v", err) From 3faf2f2b2be7c12116dffaf96f694a135cf71eb9 Mon Sep 17 00:00:00 2001 From: Dawoud Date: Mon, 22 May 2023 17:21:18 -0700 Subject: [PATCH 7/9] Fix defer function and md file --- client/interface_wireguard_test.go | 45 +++++++++++---------------- docs/resources/interface_wireguard.md | 28 ++++++++--------- 2 files changed, 32 insertions(+), 41 deletions(-) diff --git a/client/interface_wireguard_test.go b/client/interface_wireguard_test.go index 6fb63f37..4cd379b4 100644 --- a/client/interface_wireguard_test.go +++ b/client/interface_wireguard_test.go @@ -38,35 +38,28 @@ func TestAddFindDeleteInterfaceWireguard(t *testing.T) { return } defer func() { - findInterface := &InterfaceWireguard{} - findInterface.Name = name - found, err := c.Find(findInterface) + err = c.Delete(interfaceWireguard) if err != nil { t.Errorf("expected no error, got %v", err) - return } - - if _, ok := found.(Resource); !ok { - t.Error("expected found resource to implement Resource interface, but it doesn't") - return - } - if !reflect.DeepEqual(created, found) { - t.Error("expected created and found resources to be equal, but they don't") - } - err = c.Delete(found.(Resource)) - if err != nil { - t.Errorf("expected no error, got %v", err) - } - - _, err = c.Find(findInterface) - if err == nil { - t.Errorf("expected error, got nothing") - return - } - - target := &NotFound{} - if !errors.As(err, &target) { - t.Errorf("expected error to be of type %T, got %T", &NotFound{}, err) + expected := &NotFound{} + if _, err := c.Find(interfaceWireguard); err == nil || !errors.As(err, &expected) { + t.Error(err) } }() + findInterface := &InterfaceWireguard{} + findInterface.Name = name + found, err := c.Find(findInterface) + if err != nil { + t.Errorf("expected no error, got %v", err) + return + } + + if _, ok := found.(Resource); !ok { + t.Error("expected found resource to implement Resource interface, but it doesn't") + return + } + if !reflect.DeepEqual(created, found) { + t.Error("expected created and found resources to be equal, but they don't") + } } diff --git a/docs/resources/interface_wireguard.md b/docs/resources/interface_wireguard.md index 444ac06b..1cf8d998 100644 --- a/docs/resources/interface_wireguard.md +++ b/docs/resources/interface_wireguard.md @@ -1,38 +1,36 @@ # mikrotik_interface_wireguard (Resource) -Creates a Mikrotik interface_wireguard. +Creates a Mikrotik interface wireguard only supported by RouterOS v7+. +<<<<<<< HEAD ## Example Usage ```terraform resource "mikrotik_interface_wireguard" "interface_wireguard" { name = "interface_wireguard-name" } ``` +======= + +>>>>>>> bc5aef0 (Fix defer function and md file) ## Schema ### Required -- `name` (String) Name of the tunnel. +- `name` (String) Name of the interface wireguard. ### Optional -- `comment` (String) Short description of the tunnel. -- `disabled` (Boolean) Enables/disables the tunnel. Default: `false` -- `listen_port` (Number) Port for WireGuard service to listen on for incoming sessions. Default: `13231` -- `mtu` (Number) Layer3 Maximum transmission unit. Default: `1420` -- `private_key` (String) A base64 private key. If not specified, it will be automatically generated upon interface creation. -- - +- `comment` (String) Comment associated with interface wireguard. +- `disabled` (Boolean) Boolean for whether or not the interface wireguard is disabled. +- `listen_port` (Number) Port for WireGuard service to listen on for incoming sessions. +- `mtu` (Number) Layer3 Maximum transmission unit. +- `private_key` (String, Sensitive) A base64 private key. If not specified, it will be automatically generated upon interface creation. ### Read-Only -- `id` (String) The ID of this resource. +- `id` (String) Identifier of this resource assigned by RouterOS - `public_key` (String) A base64 public key is calculated from the private key. - `running` (Boolean) Whether the interface is running. -## Import -Import is supported using the following syntax: -```shell -terraform import mikrotik_interface_wireguard.interface_wireguard interface_wireguard-name -``` + From f8e7863654ffe916bf539264bf7437e78e98b0f3 Mon Sep 17 00:00:00 2001 From: Dom Del Nano Date: Tue, 23 May 2023 18:23:15 -0700 Subject: [PATCH 8/9] Fix doc changes due to rebase --- docs/resources/interface_wireguard.md | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/docs/resources/interface_wireguard.md b/docs/resources/interface_wireguard.md index 1cf8d998..f31d82c6 100644 --- a/docs/resources/interface_wireguard.md +++ b/docs/resources/interface_wireguard.md @@ -1,16 +1,7 @@ # mikrotik_interface_wireguard (Resource) Creates a Mikrotik interface wireguard only supported by RouterOS v7+. -<<<<<<< HEAD -## Example Usage -```terraform -resource "mikrotik_interface_wireguard" "interface_wireguard" { - name = "interface_wireguard-name" -} -``` -======= - ->>>>>>> bc5aef0 (Fix defer function and md file) + ## Schema From 6819a92ea6abefa5ec72eb0af54d5451daa4b158 Mon Sep 17 00:00:00 2001 From: Dom Del Nano Date: Tue, 23 May 2023 18:30:26 -0700 Subject: [PATCH 9/9] Fix go.{mod,sum,work.sum} files --- .gitignore | 1 - go.mod | 2 +- go.sum | 3 --- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index bcd2dcf8..bf0227cb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ terraform-provider-mikrotik dist/ vendor -go.work.sum \ No newline at end of file diff --git a/go.mod b/go.mod index 6db26f82..ee455617 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/ddelnano/terraform-provider-mikrotik/client v0.0.0-00010101000000-000000000000 github.com/hashicorp/terraform-plugin-docs v0.13.0 github.com/hashicorp/terraform-plugin-framework v1.2.0 + github.com/hashicorp/terraform-plugin-framework-validators v0.10.0 github.com/hashicorp/terraform-plugin-go v0.14.3 github.com/hashicorp/terraform-plugin-mux v0.8.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.20.0 @@ -41,7 +42,6 @@ require ( github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/terraform-exec v0.17.2 // indirect github.com/hashicorp/terraform-json v0.14.0 // indirect - github.com/hashicorp/terraform-plugin-framework-validators v0.10.0 // indirect github.com/hashicorp/terraform-plugin-log v0.8.0 // indirect github.com/hashicorp/terraform-registry-address v0.1.0 // indirect github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect diff --git a/go.sum b/go.sum index 746c7e7f..ba2d21b5 100644 --- a/go.sum +++ b/go.sum @@ -232,7 +232,6 @@ github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaU github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= -github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc= github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= @@ -313,8 +312,6 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=