From 4f6c719d5682dcd6d41eb745d8203b2915c90236 Mon Sep 17 00:00:00 2001 From: Assaf Admi Date: Wed, 18 Sep 2024 10:15:11 +0300 Subject: [PATCH] Search webhooks by name (#271) Co-authored-by: Assaf Admi --- CHANGELOG.md | 7 ++ coralogix/clientset/webhooks-client.go | 19 ++- coralogix/data_source_coralogix_webhook.go | 114 +++++++++++++++--- .../data_source_coralogix_webhook_test.go | 31 +++-- docs/data-sources/webhook.md | 19 +-- examples/webhook/main.tf | 6 +- 6 files changed, 158 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e860c0e0..835adb11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -681,3 +681,10 @@ New Features: ### resource/coralogix_rules_group * added support for `text` option for `json_extract` rule type. + +## Release 1.18.7 + +New Features: + +### data-source/coralogix_webhook +* Added support for searching by webhook name. \ No newline at end of file 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..820c4722 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,15 +20,17 @@ import ( "log" "terraform-provider-coralogix/coralogix/clientset" - webhooks "terraform-provider-coralogix/coralogix/clientset/grpc/webhooks" - - "google.golang.org/protobuf/encoding/protojson" + "terraform-provider-coralogix/coralogix/clientset/grpc/webhooks" + "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" - + "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/types/known/wrapperspb" ) @@ -69,6 +71,21 @@ 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.ExactlyOneOf(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 +95,77 @@ 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 +182,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..be7f03ae 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), + resource.TestCheckResourceAttr("data.coralogix_webhook.test_by_id", "name", w.name), + resource.TestCheckResourceAttr("data.coralogix_webhook.test_by_id", "slack.url", w.url), + ), + }, + { + Config: testAccCoralogixResourceSlackWebhook(w) + + testAccCoralogixDataSourceWebhook_readByName(), + 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 { - return `data "coralogix_webhook" "test" { +func testAccCoralogixDataSourceWebhook_readByID() string { + return `data "coralogix_webhook" "test_by_id" { id = coralogix_webhook.test.id } ` } + +func testAccCoralogixDataSourceWebhook_readByName() string { + return `data "coralogix_webhook" "test_by_name" { + name = coralogix_webhook.test.name +} +` +} diff --git a/docs/data-sources/webhook.md b/docs/data-sources/webhook.md index 3ef7cc07..a489f236 100644 --- a/docs/data-sources/webhook.md +++ b/docs/data-sources/webhook.md @@ -2,26 +2,32 @@ # 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" { +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 +} ``` ## Schema -### Required +### Optional - `id` (String) Webhook ID. +- `name` (String) Webhook name. ### Read-Only @@ -33,7 +39,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 +50,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 +145,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 = {