Skip to content

Commit

Permalink
adding org_psk resource and org_psks datasource
Browse files Browse the repository at this point in the history
  • Loading branch information
tmunzer committed Aug 26, 2024
1 parent 1d9ff24 commit eb1462b
Show file tree
Hide file tree
Showing 9 changed files with 855 additions and 0 deletions.
55 changes: 55 additions & 0 deletions docs/resources/org_psk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
page_title: "mist_org_psk Resource - terraform-provider-mist"
subcategory: "Wi-Fi Assurance"
description: |-
This data source provides the list of Org PSKs.
---

# mist_org_psk (Resource)

This data source provides the list of Org PSKs.


## Example Usage

```terraform
resource "mist_org_psk" "psk_one" {
org_id = mist_org.terraform_test.id
name = "JNP-FR-PAR"
passphrase = "secretone"
ssid = mist_org_wlan.wlan_one.ssid
usage = "multi"
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `name` (String)
- `org_id` (String)
- `passphrase` (String, Sensitive) passphrase of the PSK (8-63 character or 64 in hex)
- `ssid` (String) SSID this PSK should be applicable to

### Optional

- `email` (String) email to send psk expiring notifications to
- `expire_time` (Number) Expire time for this PSK key (epoch time in seconds). Default `null` (as no expiration)
- `expiry_notification_time` (Number) Number of days before psk is expired. Used as to when to start sending reminder notification when the psk is about to expire
- `mac` (String) if `usage`==`single`, the mac that this PSK ties to, empty if `auto-binding`
- `macs` (List of String) if `usage`==`macs`, this list contains N number of client mac addresses or mac patterns(11:22:*) or both. This list is capped at 5000
- `max_usage` (Number) For Org PSK Only. Max concurrent users for this PSK key. Default is 0 (unlimited)
- `note` (String)
- `notify_expiry` (Boolean) If set to true, reminder notification will be sent when psk is about to expire
- `notify_on_create_or_edit` (Boolean) If set to true, notification will be sent when psk is created or edited
- `old_passphrase` (String, Sensitive) previous passphrase of the PSK if it has been rotated
- `role` (String)
- `usage` (String) enum: `macs`, `multi`, `single`
- `vlan_id` (String)

### Read-Only

- `id` (String) PSK ID


4 changes: 4 additions & 0 deletions examples/data-sources/mist_org_psks/example.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
data "mist_org_psks" "psks_vip" {
org_id = "15fca2ac-b1a6-47cc-9953-cc6906281550"
role = "vip"
}
12 changes: 12 additions & 0 deletions examples/resources/mist_org_psk/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Gateway cluster can be imported by specifying the org_id and the psk_id
terraform import mist_org_psk.psk_one 17b46405-3a6d-4715-8bb4-6bb6d06f316a.d3c42998-9012-4859-9743-6b9bee475309
```
In Terraform v1.5.0 and later, use an import block to import `mist_org_psk` with `id`=`{org_id}.{psk_id}`:
```tf
import {
to = mist_org_psk.psk_one
id = "17b46405-3a6d-4715-8bb4-6bb6d06f316a.d3c42998-9012-4859-9743-6b9bee475309"
}
7 changes: 7 additions & 0 deletions examples/resources/mist_org_psk/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
resource "mist_org_psk" "psk_one" {
org_id = mist_org.terraform_test.id
name = "JNP-FR-PAR"
passphrase = "secretone"
ssid = mist_org_wlan.wlan_one.ssid
usage = "multi"
}
290 changes: 290 additions & 0 deletions internal/provider/org_psk_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
package provider

import (
"context"
"fmt"
"strings"

"github.com/tmunzer/mistapi-go/mistapi"

"github.com/Juniper/terraform-provider-mist/internal/resource_org_psk"

"github.com/google/uuid"
"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-log/tflog"
)

var (
_ resource.Resource = &orgPskResource{}
_ resource.ResourceWithConfigure = &orgPskResource{}
_ resource.ResourceWithImportState = &orgPskResource{}
)

func NewOrgPsk() resource.Resource {
return &orgPskResource{}
}

type orgPskResource struct {
client mistapi.ClientInterface
}

func (r *orgPskResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
tflog.Info(ctx, "Configuring Mist Psk client")
if req.ProviderData == nil {
return
}

client, ok := req.ProviderData.(mistapi.ClientInterface)
if !ok {
resp.Diagnostics.AddError(
"Unexpected Data Source Configure Type",
fmt.Sprintf("Expected *mistapigo.APIClient, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)
return
}

r.client = client
}
func (r *orgPskResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_org_psk"
}

func (r *orgPskResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: docCategoryWlan + "This data source provides the list of Org PSKs.",
Attributes: resource_org_psk.OrgPskResourceSchema(ctx).Attributes,
}
}

func (r *orgPskResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
tflog.Info(ctx, "Starting Psk Create")
var plan, state resource_org_psk.OrgPskModel

diags := req.Plan.Get(ctx, &plan)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

orgId, err := uuid.Parse(plan.OrgId.ValueString())
if err != nil {
resp.Diagnostics.AddError(
"Invalid \"org_id\" value for \"org_psk\" resource",
fmt.Sprintf("Could not parse the UUID \"%s\": %s", plan.OrgId.ValueString(), err.Error()),
)
return
}

psk, diags := resource_org_psk.TerraformToSdk(ctx, &plan)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

var upsert bool = false
data, err := r.client.OrgsPsks().CreateOrgPsk(ctx, orgId, &upsert, &psk)
if err != nil {
resp.Diagnostics.AddError(
"Error creating Psk",
"Could not create Psk, unexpected error: "+err.Error(),
)
return
}

state, diags = resource_org_psk.SdkToTerraform(ctx, &data.Data)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

diags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

}

func (r *orgPskResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var state resource_org_psk.OrgPskModel

diags := resp.State.Get(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

orgId, err := uuid.Parse(state.OrgId.ValueString())
if err != nil {
resp.Diagnostics.AddError(
"Invalid \"org_id\" value for \"org_psk\" resource",
fmt.Sprintf("Could not parse the UUID \"%s\": %s", state.OrgId.ValueString(), err.Error()),
)
return
}
pskId, err := uuid.Parse(state.Id.ValueString())
if err != nil {
resp.Diagnostics.AddError(
"Invalid \"id\" value for \"org_psk\" resource",
fmt.Sprintf("Could not parse the UUID \"%s\": %s", state.Id.ValueString(), err.Error()),
)
return
}

tflog.Info(ctx, "Starting Psk Read: psk_id "+state.Id.ValueString())
httpr, err := r.client.OrgsPsks().GetOrgPsk(ctx, orgId, pskId)
if httpr.Response.StatusCode == 404 {
resp.State.RemoveResource(ctx)
return
} else if err != nil {
resp.Diagnostics.AddError(
"Error getting Psk",
"Could not get Psk, unexpected error: "+err.Error(),
)
return
}
state, diags = resource_org_psk.SdkToTerraform(ctx, &httpr.Data)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

diags = resp.State.Set(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}

func (r *orgPskResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var state, plan resource_org_psk.OrgPskModel
tflog.Info(ctx, "Starting Psk Update")

diags := resp.State.Get(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
diags = req.Plan.Get(ctx, &plan)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

psk, diags := resource_org_psk.TerraformToSdk(ctx, &plan)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

orgId, err := uuid.Parse(state.OrgId.ValueString())
if err != nil {
resp.Diagnostics.AddError(
"Invalid \"org_id\" value for \"org_psk\" resource",
fmt.Sprintf("Could not parse the UUID \"%s\": %s", state.OrgId.ValueString(), err.Error()),
)
return
}
pskId, err := uuid.Parse(state.Id.ValueString())
if err != nil {
resp.Diagnostics.AddError(
"Invalid \"id\" value for \"org_psk\" resource",
fmt.Sprintf("Could not parse the UUID \"%s\": %s", state.Id.ValueString(), err.Error()),
)
return
}

tflog.Info(ctx, "Starting Psk Update for Psk "+state.Id.ValueString())
data, err := r.client.OrgsPsks().
UpdateOrgPsk(ctx, orgId, pskId, &psk)
if err != nil {
resp.Diagnostics.AddError(
"Error updating Psk",
"Could not update Psk, unexpected error: "+err.Error(),
)
return
}

state, diags = resource_org_psk.SdkToTerraform(ctx, &data.Data)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

diags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

}

func (r *orgPskResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var state resource_org_psk.OrgPskModel

diags := resp.State.Get(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

orgId, err := uuid.Parse(state.OrgId.ValueString())
if err != nil {
resp.Diagnostics.AddError(
"Invalid \"org_id\" value for \"org_psk\" resource",
fmt.Sprintf("Could not parse the UUID \"%s\": %s", state.OrgId.ValueString(), err.Error()),
)
return
}
pskId, err := uuid.Parse(state.Id.ValueString())
if err != nil {
resp.Diagnostics.AddError(
"Invalid \"id\" value for \"org_psk\" resource",
fmt.Sprintf("Could not parse the UUID \"%s\": %s", state.Id.ValueString(), err.Error()),
)
return
}

tflog.Info(ctx, "Starting Psk Delete: psk_id "+state.Id.ValueString())
httpr, err := r.client.OrgsPsks().DeleteOrgPsk(ctx, orgId, pskId)
if httpr.StatusCode != 404 && err != nil {
resp.Diagnostics.AddError(
"Error deleting Psk",
"Could not delete Psk, unexpected error: "+err.Error(),
)
return
}
}

func (r *orgPskResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {

importIds := strings.Split(req.ID, ".")
if len(importIds) != 2 {
resp.Diagnostics.AddError(
"Invalid \"id\" value for \"org_psk\" resource",
"import \"id\" format must be \"{org_id}.{psk_id}\"",
)
return
}
_, err := uuid.Parse(importIds[0])
if err != nil {
resp.Diagnostics.AddError(
"Invalid \"org_id\" value for \"org_psk\" resource",
fmt.Sprintf("Could not parse the UUID \"%s\": %s. Import \"id\" format must be \"{org_id}.{psk_id}\"", importIds[0], err.Error()),
)
return
}
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("org_id"), importIds[0])...)

_, err = uuid.Parse(importIds[1])
if err != nil {
resp.Diagnostics.AddError(
"Invalid \"id\" value for \"org_psk\" resource",
fmt.Sprintf("Could not parse the UUID \"%s\": %s. Import \"id\" format must be \"{org_id}.{psk_id}\"", importIds[1], err.Error()),
)
return
}
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), importIds[1])...)
}
Loading

0 comments on commit eb1462b

Please sign in to comment.