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 Interface Wireguard Support #153

Closed

Conversation

DawoudMahmud
Copy link
Contributor

@DawoudMahmud DawoudMahmud commented May 10, 2023

Closes #137

This resource only exists for RouterOS v7+ so logic was included to exclude it for RouterOS v6 builds.

@DawoudMahmud DawoudMahmud force-pushed the interface-wireguard branch from f191db9 to f878e87 Compare May 10, 2023 23:33
@DawoudMahmud DawoudMahmud force-pushed the interface-wireguard branch from f878e87 to 70fdd97 Compare May 10, 2023 23:39
@DawoudMahmud DawoudMahmud changed the title Interface wireguard Add Interface Wireguard Support May 10, 2023
@jdelnano jdelnano requested review from ddelnano and jdelnano May 10, 2023 23:40
Copy link
Owner

@ddelnano ddelnano left a comment

Choose a reason for hiding this comment

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

@DawoudMahmud nice work on this! This is a pretty large code change and involves some challenges that we haven't tackled in other parts of this provider yet (sensitive properties, etc), so don't be discouraged by the number of comments :)

@@ -5,8 +5,8 @@ go 1.18
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.0.1
github.com/hashicorp/terraform-plugin-go v0.14.2
github.com/hashicorp/terraform-plugin-framework v1.2.0
Copy link
Owner

Choose a reason for hiding this comment

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

Upgrading these dependencies are not needed for adding the new resources as far as I can tell, so they should be done in another PR (if needed). Please let me know if you have trouble preventing the go toolchain from making these changes automatically and exclude the go.sum and go.mod changes from this PR.

Copy link
Owner

Choose a reason for hiding this comment

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

After reviewing this and running the tests locally, I realized this was necessary for the changes you made. Because our existing code has significant acceptance test coverage, upgrading this in place is fine. However, with most projects bumping the core sdk can be a large change that is usually best done prior to the dependent change (adding the resource functionality that needs it).

ListenPort int `mikrotik:"listen-port"`
Mtu int `mikrotik:"mtu"`
PrivateKey string `mikrotik:"private-key"`
PublicKey string `mikrotik:"public-key"` //read only property
Copy link
Owner

Choose a reason for hiding this comment

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

It seems the readonly mikrotik struct tag is missing here. When @jdelnano implemented this, it seems that was to avoid a situation where our client interface would try to change properties that are readonly. Any idea why this isn't causing an issue with the current test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah good catch, I'll add the readonly tag to public key as well. I believe the test was passing because PublicKey defaults to an empty string so it didn't show up when adding a new interface wireguard. However since Running defaults to false, the test was complaining that I was trying to create an interface wireguard with a parameter that shouldn't exist (below).

Screen Shot 2023-05-12 at 11 05 46 AM

Comment on lines 56 to 70
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)
}
Copy link
Owner

Choose a reason for hiding this comment

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

Let's wrap this in a defer right after the .Add() call is deemed successful (on line 40). See this client test as an example.

We are a bit inconsistent with how to structure these client tests, but if this assertion fails we should still trigger the delete logic (which the defer will take care of).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense, I updated the defer to mirror the style of the Bridge client test. Let me know if you have any issues with this approach.

Comment on lines 87 to 91
"private_key": schema.StringAttribute{
Optional: true,
Computed: true,
Description: "A base64 private key. If not specified, it will be automatically generated upon interface creation.",
},
Copy link
Owner

Choose a reason for hiding this comment

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

This private key is important to keep secret. Terraform has a concept of sensitive fields, and I think this needs to be one. Here is the godoc link showing what attributes are available for the StringAttribute struct.

Screen Shot 2023-05-10 at 10 43 37 PM

Please update this property to be sensitive and ideally our acceptance test would validate this is in some way as well.

In addition to this all of the provider logging (such as this) will be print this value. We likely need to introduce a way to hide fields like this. One possibility could be adding a sensitive struct tag similarly to how the readonly tag works (added in #143).

Copy link
Contributor Author

@DawoudMahmud DawoudMahmud May 12, 2023

Choose a reason for hiding this comment

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

Added sensitive attribute to PrivateKey but still need to create a sensitive struct tag

mikrotik/resource_interface_wireguard.go Show resolved Hide resolved
// 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.",
Copy link
Owner

Choose a reason for hiding this comment

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

Add the explanation about Router OS v7+ here. This will be populated in the docs written by tfplugindocs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do I just add "only supported by RouterOS v7+" at the end of the description or is there a different way to add it to let tfplugindocs populate it in the docs? I'm not too familiar with tfplugindocs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To circle back on this, I've generated the doc file with tfplugindocs

# mikrotik_interface_wireguard (Resource)
Creates a Mikrotik interface_wireguard.

!> This resource is supported for RouterOS v7+.
Copy link
Owner

Choose a reason for hiding this comment

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

It looks like these docs were edited by hand. They must be generated with the tfplugindocs tool. See my comment in the mikrotik/resource_interface_wireguard.go file on how to add the RouterOS v7 information to the autogenerated file.

Copy link
Owner

Choose a reason for hiding this comment

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

If the default resource templating isn't appropriate, you can create resource specific templates as well (like the bgp_peer resource).

Comment on lines 56 to 72
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)
}
}()
Copy link
Owner

Choose a reason for hiding this comment

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

I'm pretty confident the placement of the defer matters. For example, an error from line 43 will cause the defer to get skipped completely.

We should place the defer right after the creation happens to ensure it is registered after the creation completes.

Copy link
Owner

Choose a reason for hiding this comment

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

Here's an example that showcases this.

Screen Shot 2023-05-13 at 12 20 12 AM

@ddelnano ddelnano mentioned this pull request May 16, 2023
1 task
@ddelnano
Copy link
Owner

This PR was completed in #159. An earlier change was merged that introduced a conflict to the go.{mod,sum} files and #159 addressed that rebase.

Thanks @DawoudMahmud for the contribution! WireGuard support is a great addition considering its growing popularity!

@ddelnano ddelnano closed this May 24, 2023
@ddelnano ddelnano added the enhancement New feature or request label May 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create mikrotik_interface_wireguard resource
2 participants