0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-06-30 02:31:10 +00:00

fix(access): change acl internal ID from url path format to position-based format (#1282)

Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
Pavel Boldyrev 2024-05-09 23:53:16 -04:00 committed by GitHub
parent 63ae88a108
commit c6019aa432
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 22 additions and 62 deletions

View File

@ -67,6 +67,6 @@ Import is supported using the following syntax:
```shell
#!/usr/bin/env sh
# ACL can be imported using its unique identifier, e.g.: {path}?entity_id={group|user@realm|user@realm!token}?role_id={role}
terraform import proxmox_virtual_environment_acl.operations_automation_monitoring /?entity_id=monitor@pve&role_id=operations-monitoring
# ACL can be imported using its unique identifier, e.g.: {path}?{group|user@realm|user@realm!token}?{role}
terraform import proxmox_virtual_environment_acl.operations_automation_monitoring /?monitor@pve?operations-monitoring
```

View File

@ -1,3 +1,3 @@
#!/usr/bin/env sh
# ACL can be imported using its unique identifier, e.g.: {path}?entity_id={group|user@realm|user@realm!token}?role_id={role}
terraform import proxmox_virtual_environment_acl.operations_automation_monitoring /?entity_id=monitor@pve&role_id=operations-monitoring
# ACL can be imported using its unique identifier, e.g.: {path}?{group|user@realm|user@realm!token}?{role}
terraform import proxmox_virtual_environment_acl.operations_automation_monitoring /?monitor@pve?operations-monitoring

View File

@ -144,11 +144,7 @@ func (r *aclResource) Create(ctx context.Context, req resource.CreateRequest, re
return
}
err = plan.generateID()
if err != nil {
resp.Diagnostics.AddError("Unable to create ACL", "failed to generate ID: "+err.Error())
return
}
plan.ID = plan.generateID()
resp.Diagnostics.Append(resp.State.Set(ctx, plan)...)
}

View File

@ -8,10 +8,8 @@ package access
import (
"fmt"
"net/url"
"strings"
"github.com/gorilla/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
proxmoxtypes "github.com/bpg/terraform-provider-proxmox/proxmox/types"
@ -30,70 +28,41 @@ type aclResourceModel struct {
UserID types.String `tfsdk:"user_id"`
}
type aclResourceIDFields struct {
EntityID string `schema:"entity_id"`
RoleID string `schema:"role_id"`
}
const aclIDFormat = "{path}?{group|user@realm|user@realm!token}?{role}"
const aclIDFormat = "{path}?entity_id={group|user@realm|user@realm!token}?role_id={role}"
func (r *aclResourceModel) generateID() types.String {
entityID := r.GroupID.ValueString() + r.TokenID.ValueString() + r.UserID.ValueString()
func (r *aclResourceModel) generateID() error {
encoder := schema.NewEncoder()
fields := aclResourceIDFields{
EntityID: r.GroupID.ValueString() + r.TokenID.ValueString() + r.UserID.ValueString(),
RoleID: r.RoleID,
}
v := url.Values{}
err := encoder.Encode(fields, v)
if err != nil {
return fmt.Errorf("failed to encode ACL resource ID: %w", err)
}
r.ID = types.StringValue(r.Path + "?" + v.Encode())
return nil
return types.StringValue(r.Path + "?" + entityID + "?" + r.RoleID)
}
func parseACLResourceModelFromID(id string) (*aclResourceModel, error) {
path, query, found := strings.Cut(id, "?")
if !found {
parts := strings.Split(id, "?")
if len(parts) != 3 {
return nil, fmt.Errorf("invalid ACL resource ID format %#v, expected %v", id, aclIDFormat)
}
v, err := url.ParseQuery(query)
if err != nil {
return nil, fmt.Errorf("invalid ACL resource ID format %#v, expected %v: %w", id, aclIDFormat, err)
}
decoder := schema.NewDecoder()
fields := aclResourceIDFields{}
err = decoder.Decode(&fields, v)
if err != nil {
return nil, fmt.Errorf("invalid ACL resource ID format %#v, expected %v: %w", id, aclIDFormat, err)
}
path := parts[0]
entityID := parts[1]
roleID := parts[2]
model := &aclResourceModel{
ID: types.StringValue(id),
GroupID: types.StringNull(),
Path: path,
Propagate: false,
RoleID: fields.RoleID,
RoleID: roleID,
TokenID: types.StringNull(),
UserID: types.StringNull(),
}
switch {
case strings.Contains(fields.EntityID, "!"):
model.TokenID = types.StringValue(fields.EntityID)
case strings.Contains(fields.EntityID, "@"):
model.UserID = types.StringValue(fields.EntityID)
case strings.Contains(entityID, "!"):
model.TokenID = types.StringValue(entityID)
case strings.Contains(entityID, "@"):
model.UserID = types.StringValue(entityID)
default:
model.GroupID = types.StringValue(fields.EntityID)
model.GroupID = types.StringValue(entityID)
}
return model, nil

View File

@ -9,7 +9,6 @@ package tests
import (
"context"
"fmt"
"net/url"
"regexp"
"testing"
@ -161,14 +160,10 @@ func testAccACLImportStateIDFunc() resource.ImportStateIdFunc {
groupID := rs.Primary.Attributes["group_id"]
tokenID := rs.Primary.Attributes["token_id"]
userID := rs.Primary.Attributes["user_id"]
entityID := groupID + tokenID + userID
roleID := rs.Primary.Attributes["role_id"]
v := url.Values{
"entity_id": []string{groupID + tokenID + userID},
"role_id": []string{roleID},
}
return path + "?" + v.Encode(), nil
return path + "?" + entityID + "?" + roleID, nil
}
}