Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# First create a security list
resource "elasticstack_kibana_security_list" "my_list" {
list_id = "allowed_domains"
name = "Allowed Domains"
description = "List of allowed domains"
type = "keyword"
}

# Add an item to the list
resource "elasticstack_kibana_security_list_item" "domain_example" {
list_id = elasticstack_kibana_security_list.my_list.list_id
value = "example.com"
meta = jsonencode({
category = "internal"
owner = "infrastructure-team"
note = "Primary internal domain"
})
}
59 changes: 47 additions & 12 deletions internal/clients/kibana_oapi/security_lists.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package kibana_oapi

import (
"context"
"encoding/json"
"net/http"

"github.com/elastic/terraform-provider-elasticstack/generated/kbapi"
Expand All @@ -26,15 +27,20 @@ func CreateListIndex(ctx context.Context, client *Client, spaceId string) diag.D
}

// GetList reads a security list from the API by ID
func GetList(ctx context.Context, client *Client, spaceId string, params *kbapi.ReadListParams) (*kbapi.ReadListResponse, diag.Diagnostics) {
func GetList(ctx context.Context, client *Client, spaceId string, params *kbapi.ReadListParams) (*kbapi.SecurityListsAPIList, diag.Diagnostics) {
resp, err := client.API.ReadListWithResponse(ctx, kbapi.SpaceId(spaceId), params)
if err != nil {
return nil, diagutil.FrameworkDiagFromError(err)
}

switch resp.StatusCode() {
case http.StatusOK:
return resp, nil
if resp.JSON200 == nil {
return nil, diag.Diagnostics{
diag.NewErrorDiagnostic("Failed to parse list response", "API returned 200 but JSON200 is nil"),
}
}
return resp.JSON200, nil
case http.StatusNotFound:
return nil, nil
default:
Expand All @@ -43,30 +49,40 @@ func GetList(ctx context.Context, client *Client, spaceId string, params *kbapi.
}

// CreateList creates a new security list.
func CreateList(ctx context.Context, client *Client, spaceId string, body kbapi.CreateListJSONRequestBody) (*kbapi.CreateListResponse, diag.Diagnostics) {
func CreateList(ctx context.Context, client *Client, spaceId string, body kbapi.CreateListJSONRequestBody) (*kbapi.SecurityListsAPIList, diag.Diagnostics) {
resp, err := client.API.CreateListWithResponse(ctx, kbapi.SpaceId(spaceId), body)
if err != nil {
return nil, diagutil.FrameworkDiagFromError(err)
}

switch resp.StatusCode() {
case http.StatusOK:
return resp, nil
if resp.JSON200 == nil {
return nil, diag.Diagnostics{
diag.NewErrorDiagnostic("Failed to parse list response", "API returned 200 but JSON200 is nil"),
}
}
return resp.JSON200, nil
default:
return nil, reportUnknownError(resp.StatusCode(), resp.Body)
}
}

// UpdateList updates an existing security list.
func UpdateList(ctx context.Context, client *Client, spaceId string, body kbapi.UpdateListJSONRequestBody) (*kbapi.UpdateListResponse, diag.Diagnostics) {
func UpdateList(ctx context.Context, client *Client, spaceId string, body kbapi.UpdateListJSONRequestBody) (*kbapi.SecurityListsAPIList, diag.Diagnostics) {
resp, err := client.API.UpdateListWithResponse(ctx, kbapi.SpaceId(spaceId), body)
if err != nil {
return nil, diagutil.FrameworkDiagFromError(err)
}

switch resp.StatusCode() {
case http.StatusOK:
return resp, nil
if resp.JSON200 == nil {
return nil, diag.Diagnostics{
diag.NewErrorDiagnostic("Failed to parse list response", "API returned 200 but JSON200 is nil"),
}
}
return resp.JSON200, nil
default:
return nil, reportUnknownError(resp.StatusCode(), resp.Body)
}
Expand All @@ -90,15 +106,24 @@ func DeleteList(ctx context.Context, client *Client, spaceId string, params *kba
}

// GetListItem reads a security list item from the API by ID or list_id and value
func GetListItem(ctx context.Context, client *Client, spaceId string, params *kbapi.ReadListItemParams) (*kbapi.ReadListItemResponse, diag.Diagnostics) {
// The response can be a single item or an array, so we unmarshal from the body.
// When querying by ID, we expect a single item.
func GetListItem(ctx context.Context, client *Client, spaceId string, params *kbapi.ReadListItemParams) (*kbapi.SecurityListsAPIListItem, diag.Diagnostics) {
resp, err := client.API.ReadListItemWithResponse(ctx, kbapi.SpaceId(spaceId), params)
if err != nil {
return nil, diagutil.FrameworkDiagFromError(err)
}

switch resp.StatusCode() {
case http.StatusOK:
return resp, nil
var listItem kbapi.SecurityListsAPIListItem
if err := json.Unmarshal(resp.Body, &listItem); err != nil {
return nil, diag.Diagnostics{
diag.NewErrorDiagnostic("Failed to parse list item response", err.Error()),
}
}

return &listItem, nil
case http.StatusNotFound:
return nil, nil
default:
Expand All @@ -107,30 +132,40 @@ func GetListItem(ctx context.Context, client *Client, spaceId string, params *kb
}

// CreateListItem creates a new security list item.
func CreateListItem(ctx context.Context, client *Client, spaceId string, body kbapi.CreateListItemJSONRequestBody) (*kbapi.CreateListItemResponse, diag.Diagnostics) {
func CreateListItem(ctx context.Context, client *Client, spaceId string, body kbapi.CreateListItemJSONRequestBody) (*kbapi.SecurityListsAPIListItem, diag.Diagnostics) {
resp, err := client.API.CreateListItemWithResponse(ctx, kbapi.SpaceId(spaceId), body)
if err != nil {
return nil, diagutil.FrameworkDiagFromError(err)
}

switch resp.StatusCode() {
case http.StatusOK:
return resp, nil
if resp.JSON200 == nil {
return nil, diag.Diagnostics{
diag.NewErrorDiagnostic("Failed to parse list item response", "API returned 200 but JSON200 is nil"),
}
}
return resp.JSON200, nil
default:
return nil, reportUnknownError(resp.StatusCode(), resp.Body)
}
}

// UpdateListItem updates an existing security list item.
func UpdateListItem(ctx context.Context, client *Client, spaceId string, body kbapi.UpdateListItemJSONRequestBody) (*kbapi.UpdateListItemResponse, diag.Diagnostics) {
func UpdateListItem(ctx context.Context, client *Client, spaceId string, body kbapi.UpdateListItemJSONRequestBody) (*kbapi.SecurityListsAPIListItem, diag.Diagnostics) {
resp, err := client.API.UpdateListItemWithResponse(ctx, kbapi.SpaceId(spaceId), body)
if err != nil {
return nil, diagutil.FrameworkDiagFromError(err)
}

switch resp.StatusCode() {
case http.StatusOK:
return resp, nil
if resp.JSON200 == nil {
return nil, diag.Diagnostics{
diag.NewErrorDiagnostic("Failed to parse list item response", "API returned 200 but JSON200 is nil"),
}
}
return resp.JSON200, nil
default:
return nil, reportUnknownError(resp.StatusCode(), resp.Body)
}
Expand Down
12 changes: 6 additions & 6 deletions internal/kibana/security_list/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,36 +31,36 @@ func (r *securityListResource) Create(ctx context.Context, req resource.CreateRe

// Create the list
spaceID := plan.SpaceID.ValueString()
createResp, diags := kibana_oapi.CreateList(ctx, client, spaceID, *createReq)
createdList, diags := kibana_oapi.CreateList(ctx, client, spaceID, *createReq)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

if createResp == nil || createResp.JSON200 == nil {
if createdList == nil {
resp.Diagnostics.AddError("Failed to create security list", "API returned empty response")
return
}

// Read the created list to populate state
readParams := &kbapi.ReadListParams{
Id: createResp.JSON200.Id,
Id: createdList.Id,
}

readResp, diags := kibana_oapi.GetList(ctx, client, spaceID, readParams)
list, diags := kibana_oapi.GetList(ctx, client, spaceID, readParams)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

if readResp == nil || readResp.JSON200 == nil {
if list == nil {
resp.State.RemoveResource(ctx)
resp.Diagnostics.AddError("Failed to fetch security list", "API returned empty response")
return
}

// Update state with read response
diags = plan.fromAPI(ctx, readResp.JSON200)
diags = plan.fromAPI(ctx, list)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
Expand Down
15 changes: 8 additions & 7 deletions internal/kibana/security_list/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/elastic/terraform-provider-elasticstack/generated/kbapi"
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
"github.com/elastic/terraform-provider-elasticstack/internal/utils/typeutils"
"github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
Expand Down Expand Up @@ -120,10 +121,10 @@ func (m *SecurityListModel) fromAPI(ctx context.Context, apiList *kbapi.Security
}
m.ID = types.StringValue(compId.String())

m.ListID = utils.StringishValue(apiList.Id)
m.Name = utils.StringishValue(apiList.Name)
m.Description = utils.StringishValue(apiList.Description)
m.Type = utils.StringishValue(apiList.Type)
m.ListID = typeutils.StringishValue(apiList.Id)
m.Name = typeutils.StringishValue(apiList.Name)
m.Description = typeutils.StringishValue(apiList.Description)
m.Type = typeutils.StringishValue(apiList.Type)
m.Immutable = types.BoolValue(apiList.Immutable)
m.Version = types.Int64Value(int64(apiList.Version))
m.TieBreakerID = types.StringValue(apiList.TieBreakerId)
Expand All @@ -133,11 +134,11 @@ func (m *SecurityListModel) fromAPI(ctx context.Context, apiList *kbapi.Security
m.UpdatedBy = types.StringValue(apiList.UpdatedBy)

// Set optional _version field
m.VersionID = utils.StringishPointerValue(apiList.UnderscoreVersion)
m.VersionID = typeutils.StringishPointerValue(apiList.UnderscoreVersion)

m.Deserializer = utils.StringishPointerValue(apiList.Deserializer)
m.Deserializer = typeutils.StringishPointerValue(apiList.Deserializer)

m.Serializer = utils.StringishPointerValue(apiList.Serializer)
m.Serializer = typeutils.StringishPointerValue(apiList.Serializer)

if apiList.Meta != nil {
metaBytes, err := json.Marshal(apiList.Meta)
Expand Down
6 changes: 3 additions & 3 deletions internal/kibana/security_list/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,19 @@ func (r *securityListResource) Read(ctx context.Context, req resource.ReadReques
Id: kbapi.SecurityListsAPIListId(listID),
}

readResp, diags := kibana_oapi.GetList(ctx, client, spaceID, params)
list, diags := kibana_oapi.GetList(ctx, client, spaceID, params)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

if readResp == nil || readResp.JSON200 == nil {
if list == nil {
resp.State.RemoveResource(ctx)
return
}

// Convert API response to model
diags = state.fromAPI(ctx, readResp.JSON200)
diags = state.fromAPI(ctx, list)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
Expand Down
2 changes: 1 addition & 1 deletion internal/kibana/security_list/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func (r *securityListResource) Schema(_ context.Context, _ resource.SchemaReques
Computed: true,
},
"version_id": schema.StringAttribute{
MarkdownDescription: "The version id, normally returned by the API when the document is retrieved. Use it ensure updates are done against the latest version.",
MarkdownDescription: "The version id, normally returned by the API when the document is retrieved. Use it to ensure updates are done against the latest version.",
Computed: true,
},
"immutable": schema.BoolAttribute{
Expand Down
12 changes: 6 additions & 6 deletions internal/kibana/security_list/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,36 +37,36 @@ func (r *securityListResource) Update(ctx context.Context, req resource.UpdateRe

// Update the list
spaceID := plan.SpaceID.ValueString()
updateResp, diags := kibana_oapi.UpdateList(ctx, client, spaceID, *updateReq)
updatedList, diags := kibana_oapi.UpdateList(ctx, client, spaceID, *updateReq)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

if updateResp == nil || updateResp.JSON200 == nil {
if updatedList == nil {
resp.Diagnostics.AddError("Failed to update security list", "API returned empty response")
return
}

// Read the updated list to populate state
readParams := &kbapi.ReadListParams{
Id: updateResp.JSON200.Id,
Id: updatedList.Id,
}

readResp, diags := kibana_oapi.GetList(ctx, client, spaceID, readParams)
list, diags := kibana_oapi.GetList(ctx, client, spaceID, readParams)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

if readResp == nil || readResp.JSON200 == nil {
if list == nil {
resp.State.RemoveResource(ctx)
resp.Diagnostics.AddError("Failed to fetch security list", "API returned empty response")
return
}

// Update state with read response
diags = plan.fromAPI(ctx, readResp.JSON200)
diags = plan.fromAPI(ctx, list)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
Expand Down
Loading