mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-08-22 19:38:35 +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:
parent
63ae88a108
commit
c6019aa432
@ -67,6 +67,6 @@ Import is supported using the following syntax:
|
|||||||
|
|
||||||
```shell
|
```shell
|
||||||
#!/usr/bin/env sh
|
#!/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}
|
# 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 /?entity_id=monitor@pve&role_id=operations-monitoring
|
terraform import proxmox_virtual_environment_acl.operations_automation_monitoring /?monitor@pve?operations-monitoring
|
||||||
```
|
```
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
#!/usr/bin/env sh
|
#!/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}
|
# 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 /?entity_id=monitor@pve&role_id=operations-monitoring
|
terraform import proxmox_virtual_environment_acl.operations_automation_monitoring /?monitor@pve?operations-monitoring
|
||||||
|
@ -144,11 +144,7 @@ func (r *aclResource) Create(ctx context.Context, req resource.CreateRequest, re
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = plan.generateID()
|
plan.ID = plan.generateID()
|
||||||
if err != nil {
|
|
||||||
resp.Diagnostics.AddError("Unable to create ACL", "failed to generate ID: "+err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, plan)...)
|
resp.Diagnostics.Append(resp.State.Set(ctx, plan)...)
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,8 @@ package access
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gorilla/schema"
|
|
||||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||||
|
|
||||||
proxmoxtypes "github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
proxmoxtypes "github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||||
@ -30,70 +28,41 @@ type aclResourceModel struct {
|
|||||||
UserID types.String `tfsdk:"user_id"`
|
UserID types.String `tfsdk:"user_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type aclResourceIDFields struct {
|
const aclIDFormat = "{path}?{group|user@realm|user@realm!token}?{role}"
|
||||||
EntityID string `schema:"entity_id"`
|
|
||||||
RoleID string `schema:"role_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
return types.StringValue(r.Path + "?" + entityID + "?" + r.RoleID)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseACLResourceModelFromID(id string) (*aclResourceModel, error) {
|
func parseACLResourceModelFromID(id string) (*aclResourceModel, error) {
|
||||||
path, query, found := strings.Cut(id, "?")
|
parts := strings.Split(id, "?")
|
||||||
|
if len(parts) != 3 {
|
||||||
if !found {
|
|
||||||
return nil, fmt.Errorf("invalid ACL resource ID format %#v, expected %v", id, aclIDFormat)
|
return nil, fmt.Errorf("invalid ACL resource ID format %#v, expected %v", id, aclIDFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err := url.ParseQuery(query)
|
path := parts[0]
|
||||||
if err != nil {
|
entityID := parts[1]
|
||||||
return nil, fmt.Errorf("invalid ACL resource ID format %#v, expected %v: %w", id, aclIDFormat, err)
|
roleID := parts[2]
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
model := &aclResourceModel{
|
model := &aclResourceModel{
|
||||||
ID: types.StringValue(id),
|
ID: types.StringValue(id),
|
||||||
GroupID: types.StringNull(),
|
GroupID: types.StringNull(),
|
||||||
Path: path,
|
Path: path,
|
||||||
Propagate: false,
|
Propagate: false,
|
||||||
RoleID: fields.RoleID,
|
RoleID: roleID,
|
||||||
TokenID: types.StringNull(),
|
TokenID: types.StringNull(),
|
||||||
UserID: types.StringNull(),
|
UserID: types.StringNull(),
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case strings.Contains(fields.EntityID, "!"):
|
case strings.Contains(entityID, "!"):
|
||||||
model.TokenID = types.StringValue(fields.EntityID)
|
model.TokenID = types.StringValue(entityID)
|
||||||
case strings.Contains(fields.EntityID, "@"):
|
case strings.Contains(entityID, "@"):
|
||||||
model.UserID = types.StringValue(fields.EntityID)
|
model.UserID = types.StringValue(entityID)
|
||||||
default:
|
default:
|
||||||
model.GroupID = types.StringValue(fields.EntityID)
|
model.GroupID = types.StringValue(entityID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return model, nil
|
return model, nil
|
||||||
|
@ -9,7 +9,6 @@ package tests
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -161,14 +160,10 @@ func testAccACLImportStateIDFunc() resource.ImportStateIdFunc {
|
|||||||
groupID := rs.Primary.Attributes["group_id"]
|
groupID := rs.Primary.Attributes["group_id"]
|
||||||
tokenID := rs.Primary.Attributes["token_id"]
|
tokenID := rs.Primary.Attributes["token_id"]
|
||||||
userID := rs.Primary.Attributes["user_id"]
|
userID := rs.Primary.Attributes["user_id"]
|
||||||
|
entityID := groupID + tokenID + userID
|
||||||
|
|
||||||
roleID := rs.Primary.Attributes["role_id"]
|
roleID := rs.Primary.Attributes["role_id"]
|
||||||
|
|
||||||
v := url.Values{
|
return path + "?" + entityID + "?" + roleID, nil
|
||||||
"entity_id": []string{groupID + tokenID + userID},
|
|
||||||
"role_id": []string{roleID},
|
|
||||||
}
|
|
||||||
|
|
||||||
return path + "?" + v.Encode(), nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user