diff --git a/coralogix/clientset/webhooks-client.go b/coralogix/clientset/webhooks-client.go index 94725590..58dba54b 100644 --- a/coralogix/clientset/webhooks-client.go +++ b/coralogix/clientset/webhooks-client.go @@ -1,11 +1,11 @@ // Copyright 2024 Coralogix Ltd. -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // https://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -76,6 +76,19 @@ func (c WebhooksClient) DeleteWebhook(ctx context.Context, req *webhooks.DeleteO return client.DeleteOutgoingWebhook(callProperties.Ctx, req, callProperties.CallOptions...) } +func (c WebhooksClient) ListWebhooks(ctx context.Context, req *webhooks.ListAllOutgoingWebhooksRequest) (*webhooks.ListAllOutgoingWebhooksResponse, error) { + callProperties, err := c.callPropertiesCreator.GetCallProperties(ctx) + if err != nil { + return nil, err + } + + conn := callProperties.Connection + defer conn.Close() + client := webhooks.NewOutgoingWebhooksServiceClient(conn) + + return client.ListAllOutgoingWebhooks(callProperties.Ctx, req, callProperties.CallOptions...) +} + func NewWebhooksClient(c *CallPropertiesCreator) *WebhooksClient { return &WebhooksClient{callPropertiesCreator: c} } diff --git a/coralogix/data_source_coralogix_webhook.go b/coralogix/data_source_coralogix_webhook.go index 5d01a7eb..1af3f0c0 100644 --- a/coralogix/data_source_coralogix_webhook.go +++ b/coralogix/data_source_coralogix_webhook.go @@ -1,11 +1,11 @@ // Copyright 2024 Coralogix Ltd. -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // https://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,12 +20,16 @@ import ( "log" "terraform-provider-coralogix/coralogix/clientset" - webhooks "terraform-provider-coralogix/coralogix/clientset/grpc/webhooks" + "terraform-provider-coralogix/coralogix/clientset/grpc/webhooks" "google.golang.org/protobuf/encoding/protojson" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -69,6 +73,22 @@ func (d *WebhookDataSource) Schema(ctx context.Context, _ datasource.SchemaReque r.Schema(ctx, resource.SchemaRequest{}, &resourceResp) resp.Schema = frameworkDatasourceSchemaFromFrameworkResourceSchema(resourceResp.Schema) + + if idAttr, ok := resp.Schema.Attributes["id"].(schema.StringAttribute); ok { + idAttr.Required = false + idAttr.Optional = true + idAttr.Validators = []validator.String{ + stringvalidator.ConflictsWith(path.MatchRelative().AtParent().AtName("name")), + } + resp.Schema.Attributes["id"] = idAttr + } + + if nameAttr, ok := resp.Schema.Attributes["name"].(schema.StringAttribute); ok { + nameAttr.Required = false + nameAttr.Optional = true + + resp.Schema.Attributes["name"] = nameAttr + } } func (d *WebhookDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { @@ -78,10 +98,78 @@ func (d *WebhookDataSource) Read(ctx context.Context, req datasource.ReadRequest return } - //Get refreshed Webhook value from Coralogix id := data.ID.ValueString() - log.Printf("[INFO] Reading Webhook: %s", id) + name := data.Name.ValueString() + + var getWebhookResp *webhooks.GetOutgoingWebhookResponse + var err error + + if id != "" { + getWebhookResp, err = d.fetchWebhookByID(ctx, id, resp) + if err != nil { + return + } + + } else if name != "" { + log.Printf("[INFO] Listing Webhooks to find by name: %s", name) + listWebhookReq := &webhooks.ListAllOutgoingWebhooksRequest{} + listWebhookResp, err := d.client.ListWebhooks(ctx, listWebhookReq) + + if err != nil { + log.Printf("[ERROR] Received error when listing webhooks: %s", err.Error()) + listWebhookReqStr := protojson.Format(listWebhookReq) + resp.Diagnostics.AddError( + "Error listing Webhooks", + formatRpcErrors(err, "ListWebhooks", listWebhookReqStr), + ) + return + } + + var webhookID string + var found bool + for _, webhookSummary := range listWebhookResp.GetDeployed() { + if webhookSummary.GetName().GetValue() == name { + if found { + resp.Diagnostics.AddError( + "Multiple Webhooks Found", + fmt.Sprintf("Multiple webhooks found with name %q", name), + ) + return + } + found = true + log.Printf("[INFO] Found Webhook ID by name: %s", webhookSummary.GetId().GetValue()) + webhookID = webhookSummary.GetId().GetValue() + } + } + + if webhookID == "" { + resp.Diagnostics.AddError( + "Webhook Not Found", + fmt.Sprintf("No webhook found with name %q", name), + ) + return + } + + getWebhookResp, err = d.fetchWebhookByID(ctx, webhookID, resp) + if err != nil { + return + } + } + log.Printf("[INFO] Received Webhook: %s", protojson.Format(getWebhookResp)) + + data, diags := flattenWebhook(ctx, getWebhookResp.GetWebhook()) + if diags.HasError() { + resp.Diagnostics = diags + return + } + + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (d *WebhookDataSource) fetchWebhookByID(ctx context.Context, id string, resp *datasource.ReadResponse) (*webhooks.GetOutgoingWebhookResponse, error) { + log.Printf("[INFO] Reading Webhook by ID: %s", id) getWebhookReq := &webhooks.GetOutgoingWebhookRequest{Id: wrapperspb.String(id)} getWebhookResp, err := d.client.GetWebhook(ctx, getWebhookReq) if err != nil { @@ -98,15 +186,7 @@ func (d *WebhookDataSource) Read(ctx context.Context, req datasource.ReadRequest formatRpcErrors(err, "Webhook", reqStr), ) } - return + return nil, err } - log.Printf("[INFO] Received Webhook: %s", protojson.Format(getWebhookResp)) - - data, diags := flattenWebhook(ctx, getWebhookResp.GetWebhook()) - if diags.HasError() { - resp.Diagnostics = diags - return - } - // Save data into Terraform state - resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) + return getWebhookResp, nil } diff --git a/coralogix/data_source_coralogix_webhook_test.go b/coralogix/data_source_coralogix_webhook_test.go index 444e986b..c9f7b353 100644 --- a/coralogix/data_source_coralogix_webhook_test.go +++ b/coralogix/data_source_coralogix_webhook_test.go @@ -1,11 +1,11 @@ // Copyright 2024 Coralogix Ltd. -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // https://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,19 +30,34 @@ func TestAccCoralogixDataSourceWebhook_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccCoralogixResourceSlackWebhook(w) + - testAccCoralogixDataSourceWebhook_read(), + testAccCoralogixDataSourceWebhook_readByID(), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("data.coralogix_webhook.test", "name", w.name), resource.TestCheckResourceAttr("data.coralogix_webhook.test", "slack.url", w.url), ), }, + { + Config: testAccCoralogixResourceSlackWebhook(w) + + testAccCoralogixDataSourceWebhook_readByName(w.name), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.coralogix_webhook.test_by_name", "name", w.name), + resource.TestCheckResourceAttr("data.coralogix_webhook.test_by_name", "slack.url", w.url), + ), + }, }, }) } -func testAccCoralogixDataSourceWebhook_read() string { +func testAccCoralogixDataSourceWebhook_readByID() string { return `data "coralogix_webhook" "test" { id = coralogix_webhook.test.id } ` } + +func testAccCoralogixDataSourceWebhook_readByName(name string) string { + return `data "coralogix_webhook" "test_by_name" { + name = "` + name + `" + } +` +} diff --git a/docs/data-sources/webhook.md b/docs/data-sources/webhook.md index 3ef7cc07..144cbf84 100644 --- a/docs/data-sources/webhook.md +++ b/docs/data-sources/webhook.md @@ -2,26 +2,35 @@ # generated by https://github.com/hashicorp/terraform-plugin-docs page_title: "coralogix_webhook Data Source - terraform-provider-coralogix" subcategory: "" -description: "Coralogix webhook. For more info please review - https://coralogix.com/docs/alert-webhook-with-slack/." +description: |- + Coralogix webhook. For more info please review - https://coralogix.com/docs/coralogix-Webhook-extension/. --- # coralogix_webhook (Data Source) -Coralogix webhook. For more info please review - https://coralogix.com/docs/alert-webhook-with-slack/. + +Coralogix webhook. For more info please review - https://coralogix.com/docs/coralogix-Webhook-extension/. -## Example Usage -```hcl -data "coralogix_webhook" "imported_webhook" { - id = coralogix_webhook.slack_webhook.id -} -``` ## Schema -### Required +### Optional - `id` (String) Webhook ID. +- `name` (String) Webhook name. + +## Example Usage + +```hcl +data "coralogix_webhook" "imported_webhook_by_id" { + id = coralogix_webhook.slack_webhook.id +} + +data "coralogix_webhook" "imported_webhook_by_name" { + id = coralogix_webhook.slack_webhook.name +} +``` ### Read-Only @@ -33,7 +42,6 @@ data "coralogix_webhook" "imported_webhook" { - `jira` (Attributes) Jira webhook. (see [below for nested schema](#nestedatt--jira)) - `microsoft_teams` (Attributes) Microsoft Teams webhook. (Deprecated, please use microsoft_teams_workflow) (see [below for nested schema](#nestedatt--microsoft_teams)) - `microsoft_teams_workflow` (Attributes) Microsoft Teams Workflow webhook. (see [below for nested schema](#nestedatt--microsoft_teams_workflow)) -- `name` (String) Webhook name. - `opsgenie` (Attributes) Opsgenie webhook. (see [below for nested schema](#nestedatt--opsgenie)) - `pager_duty` (Attributes) PagerDuty webhook. (see [below for nested schema](#nestedatt--pager_duty)) - `sendlog` (Attributes) Send log webhook. (see [below for nested schema](#nestedatt--sendlog)) @@ -45,7 +53,7 @@ data "coralogix_webhook" "imported_webhook" { Read-Only: - `headers` (Map of String) Webhook headers. Map of string to string. -- `method` (String) Webhook method. can be one of: put, get, post +- `method` (String) Webhook method. can be one of: post, put, get - `payload` (String) Webhook payload. JSON string. - `url` (String) Webhook URL. - `uuid` (String) Webhook UUID. Computed automatically. @@ -140,7 +148,7 @@ Read-Only: Read-Only: - `attachments` (Attributes List) Slack attachments. (see [below for nested schema](#nestedatt--slack--attachments)) -- `notify_on` (Set of String) Slack notifications. can be one of: error_and_critical_logs, flow_anomalies, spike_anomalies, data_usage +- `notify_on` (Set of String) Slack notifications. can be one of: flow_anomalies, spike_anomalies, data_usage, error_and_critical_logs - `url` (String) Slack URL. diff --git a/examples/webhook/main.tf b/examples/webhook/main.tf index e05b0d06..f43cc690 100644 --- a/examples/webhook/main.tf +++ b/examples/webhook/main.tf @@ -25,10 +25,14 @@ resource "coralogix_webhook" "slack_webhook" { } } -data "coralogix_webhook" "imported_webhook" { +data "coralogix_webhook" "imported_webhook_by_id" { id = coralogix_webhook.slack_webhook.id } +data "coralogix_webhook" "imported_webhook_by_name" { + id = coralogix_webhook.slack_webhook.name +} + resource "coralogix_webhook" "custom_webhook" { name = "custom-webhook" custom = {