From 18839e43792e180bbb902592d678b05b1e806a9e Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak Date: Fri, 13 Sep 2024 16:12:37 +0200 Subject: [PATCH 1/7] feat: add icmp and browser monitor API support to kibana rest client Implements part of https://github.com/elastic/terraform-provider-elasticstack/issues/610 --- .../kbapi/api.kibana_synthetics.go | 59 ++++++++- .../kbapi/api.kibana_synthetics_test.go | 125 ++++++++++++++++++ 2 files changed, 183 insertions(+), 1 deletion(-) diff --git a/libs/go-kibana-rest/kbapi/api.kibana_synthetics.go b/libs/go-kibana-rest/kbapi/api.kibana_synthetics.go index 54a2f3404..d4cb97855 100644 --- a/libs/go-kibana-rest/kbapi/api.kibana_synthetics.go +++ b/libs/go-kibana-rest/kbapi/api.kibana_synthetics.go @@ -46,6 +46,10 @@ const ( ModeAll HttpMonitorMode = "all" ModeAny = "any" + + ScreenshotOn ScreenshotOption = "on" + ScreenshotOff = "off" + ScreenshotOnlyOfFailures = "only-on-failure" ) var plMu sync.Mutex @@ -65,6 +69,7 @@ type MonitorType string type MonitorLocation string type MonitorSchedule int type HttpMonitorMode string +type ScreenshotOption string type JsonObject map[string]interface{} @@ -90,6 +95,19 @@ type MonitorAlertConfig struct { Tls *SyntheticsStatusConfig `json:"tls,omitempty"` } +type ICMPMonitorFields struct { + Host string `json:"host"` + Wait string `json:"wait,omitempty"` +} + +type BrowserMonitorFields struct { + InlineScript string `json:"inline_script"` + Screenshots ScreenshotOption `json:"screenshots,omitempty"` + SyntheticsArgs []string `json:"synthetics_args,omitempty"` + IgnoreHttpsErrors *bool `json:"ignore_https_errors,omitempty"` + PlaywrightOptions JsonObject `json:"playwright_options,omitempty"` +} + type TCPMonitorFields struct { Host string `json:"host"` SslVerificationMode string `json:"ssl.verification_mode,omitempty"` @@ -207,11 +225,20 @@ type SyntheticsMonitor struct { ProxyUrl string `json:"proxy_url,omitempty"` SslVerificationMode string `json:"ssl.verification_mode"` SslSupportedProtocols []string `json:"ssl.supported_protocols"` + //tcp and icmp + Host string `json:"host,omitempty"` //tcp - Host string `json:"host,omitempty"` ProxyUseLocalResolver *bool `json:"proxy_use_local_resolver,omitempty"` CheckSend string `json:"check.send,omitempty"` CheckReceive string `json:"check.receive,omitempty"` + //icmp + Wait json.Number `json:"wait,omitempty"` + //browser + Screenshots string `json:"screenshots,omitempty"` + IgnoreHttpsErrors *bool `json:"ignore_https_errors,omitempty"` + InlineScript string `json:"inline_script"` + SyntheticsArgs []string `json:"synthetics_args,omitempty"` + PlaywrightOptions JsonObject `json:"playwright_options,omitempty"` } type MonitorTypeConfig struct { @@ -248,6 +275,36 @@ func (f TCPMonitorFields) APIRequest(config SyntheticsMonitorConfig) interface{} } } +func (f ICMPMonitorFields) APIRequest(config SyntheticsMonitorConfig) interface{} { + + mType := MonitorTypeConfig{Type: Icmp} + + return struct { + SyntheticsMonitorConfig + MonitorTypeConfig + ICMPMonitorFields + }{ + config, + mType, + f, + } +} + +func (f BrowserMonitorFields) APIRequest(config SyntheticsMonitorConfig) interface{} { + + mType := MonitorTypeConfig{Type: Browser} + + return struct { + SyntheticsMonitorConfig + MonitorTypeConfig + BrowserMonitorFields + }{ + config, + mType, + f, + } +} + type KibanaSyntheticsMonitorAdd func(ctx context.Context, config SyntheticsMonitorConfig, fields MonitorFields, namespace string) (*SyntheticsMonitor, error) type KibanaSyntheticsMonitorUpdate func(ctx context.Context, id MonitorID, config SyntheticsMonitorConfig, fields MonitorFields, namespace string) (*SyntheticsMonitor, error) diff --git a/libs/go-kibana-rest/kbapi/api.kibana_synthetics_test.go b/libs/go-kibana-rest/kbapi/api.kibana_synthetics_test.go index 351c39e5e..fd527cf17 100644 --- a/libs/go-kibana-rest/kbapi/api.kibana_synthetics_test.go +++ b/libs/go-kibana-rest/kbapi/api.kibana_synthetics_test.go @@ -236,6 +236,129 @@ func (s *KBAPITestSuite) TestKibanaSyntheticsMonitorAPI() { }, }, }, + { + name: "bare minimum icmp monitor", + input: TestConfig{ + config: SyntheticsMonitorConfig{ + Name: fmt.Sprintf("test synthetics icmp monitor %s", testUuid), + PrivateLocations: []string{location.Label}, + }, + fields: ICMPMonitorFields{ + Host: "localhost", + }, + }, + update: TestConfig{ + config: SyntheticsMonitorConfig{}, + fields: ICMPMonitorFields{ + Host: "127.0.0.1", + }, + }, + }, + { + name: "all fields icmp monitor", + input: TestConfig{ + config: SyntheticsMonitorConfig{ + Name: fmt.Sprintf("test all fields icmp monitor %s", testUuid), + Schedule: Every10Minutes, + PrivateLocations: []string{location.Label}, + Enabled: f, + Tags: []string{"aaa", "bbb"}, + Alert: &MonitorAlertConfig{ + Status: &SyntheticsStatusConfig{Enabled: t}, + Tls: &SyntheticsStatusConfig{Enabled: f}, + }, + APMServiceName: "APMServiceName", + TimeoutSeconds: 42, + Namespace: space, + Params: map[string]interface{}{ + "param1": "some-params", + "my_url": "http://localhost:8080", + }, + RetestOnFailure: f, + }, + fields: ICMPMonitorFields{ + Host: "localhost", + Wait: "10", + }, + }, + update: TestConfig{ + config: SyntheticsMonitorConfig{ + Name: fmt.Sprintf("update all fields icmp monitor %s", testUuid), + Schedule: Every30Minutes, + }, + fields: ICMPMonitorFields{ + Host: "127.0.0.1", + Wait: "5", + }, + }, + }, + { + name: "bare minimum browser monitor", + input: TestConfig{ + config: SyntheticsMonitorConfig{ + Name: fmt.Sprintf("test synthetics browser monitor %s", testUuid), + PrivateLocations: []string{location.Label}, + }, + fields: BrowserMonitorFields{ + InlineScript: `step('Go to https://google.com.co', () => page.goto('https://www.google.com'))`, + }, + }, + update: TestConfig{ + config: SyntheticsMonitorConfig{ + Name: fmt.Sprintf("test synthetics browser monitor %s", testUuid), + }, + fields: BrowserMonitorFields{ + InlineScript: `step('Go to https://www.google.de', () => page.goto('https://www.google.de'))`, + }, + }, + }, + { + name: "all fields browser monitor", + input: TestConfig{ + config: SyntheticsMonitorConfig{ + Name: fmt.Sprintf("test all fields browser monitor %s", testUuid), + Schedule: Every10Minutes, + PrivateLocations: []string{location.Label}, + Enabled: f, + Tags: []string{"aaa", "bbb"}, + Alert: &MonitorAlertConfig{ + Status: &SyntheticsStatusConfig{Enabled: t}, + Tls: &SyntheticsStatusConfig{Enabled: f}, + }, + APMServiceName: "APMServiceName", + TimeoutSeconds: 42, + Namespace: space, + Params: map[string]interface{}{ + "param1": "some-params", + "my_url": "http://localhost:8080", + }, + RetestOnFailure: f, + }, + fields: BrowserMonitorFields{ + InlineScript: `step('Go to https://google.com.co', () => page.goto('https://www.google.com'))`, + Screenshots: ScreenshotOn, + SyntheticsArgs: []string{"a", "b"}, + IgnoreHttpsErrors: t, + PlaywrightOptions: map[string]interface{}{ + "ignoreHTTPSErrors": false, + "httpCredentials": map[string]interface{}{ + "username": "test", + "password": "test", + }, + }, + }, + }, + update: TestConfig{ + config: SyntheticsMonitorConfig{ + Name: fmt.Sprintf("update all fields browser monitor %s", testUuid), + Schedule: Every30Minutes, + }, + fields: BrowserMonitorFields{ + InlineScript: `step('Go to https://google.de', () => page.goto('https://www.google.de'))`, + Screenshots: ScreenshotOff, + }, + }, + }, } for _, tc := range testCases { @@ -298,6 +421,8 @@ func updateDueToKibanaAPIDiff(m *SyntheticsMonitor) { m.CheckRequestHeaders = nil m.CheckSend = "" m.CheckReceive = "" + m.InlineScript = "" + m.SyntheticsArgs = nil } func (s *KBAPITestSuite) TestKibanaSyntheticsPrivateLocationAPI() { From 3c9225ea13865a41ae92a968955ef6e1e0774b94 Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak Date: Sat, 14 Sep 2024 10:45:31 +0200 Subject: [PATCH 2/7] feat: add icmp and browser synthetic monitors implements https://github.com/elastic/terraform-provider-elasticstack/issues/610 --- docs/resources/kibana_synthetics_monitor.md | 29 ++ internal/kibana/synthetics/acc_test.go | 2 + internal/kibana/synthetics/schema.go | 194 ++++++++++++-- internal/kibana/synthetics/schema_test.go | 281 ++++++++++++++++++++ 4 files changed, 483 insertions(+), 23 deletions(-) diff --git a/docs/resources/kibana_synthetics_monitor.md b/docs/resources/kibana_synthetics_monitor.md index 37ef5de61..c56a1ee0b 100644 --- a/docs/resources/kibana_synthetics_monitor.md +++ b/docs/resources/kibana_synthetics_monitor.md @@ -65,8 +65,10 @@ resource "elasticstack_kibana_synthetics_monitor" "my_monitor" { ### Optional - `alert` (Attributes) Alert configuration. Default: `{ status: { enabled: true }, tls: { enabled: true } }`. (see [below for nested schema](#nestedatt--alert)) +- `browser` (Attributes) Browser Monitor specific fields (see [below for nested schema](#nestedatt--browser)) - `enabled` (Boolean) Whether the monitor is enabled. Default: `true` - `http` (Attributes) HTTP Monitor specific fields (see [below for nested schema](#nestedatt--http)) +- `icmp` (Attributes) ICMP Monitor specific fields (see [below for nested schema](#nestedatt--icmp)) - `locations` (List of String) Where to deploy the monitor. Monitors can be deployed in multiple locations so that you can detect differences in availability and response times across those locations. - `params` (String) Monitor parameters. Raw JSON object, use `jsonencode` function to represent JSON - `private_locations` (List of String) These Private Locations refer to locations hosted and managed by you, whereas locations are hosted by Elastic. You can specify a Private Location using the location’s name. @@ -107,6 +109,21 @@ Optional: + +### Nested Schema for `browser` + +Required: + +- `inline_script` (String) The inline script. + +Optional: + +- `ignore_https_errors` (Boolean) Whether to ignore HTTPS errors. +- `playwright_options` (String) Playwright options.. Raw JSON object, use `jsonencode` function to represent JSON +- `screenshots` (String) Controls the behavior of the screenshots feature. +- `synthetics_args` (List of String) Synthetics agent CLI arguments. + + ### Nested Schema for `http` @@ -130,6 +147,18 @@ Optional: - `username` (String) The username for authenticating with the server. The credentials are passed with the request. + +### Nested Schema for `icmp` + +Required: + +- `host` (String) Host to ping; it can be an IP address or a hostname. + +Optional: + +- `wait` (Number) Wait time in seconds. Default: `1` + + ### Nested Schema for `tcp` diff --git a/internal/kibana/synthetics/acc_test.go b/internal/kibana/synthetics/acc_test.go index 487353d4e..dfbd26d47 100644 --- a/internal/kibana/synthetics/acc_test.go +++ b/internal/kibana/synthetics/acc_test.go @@ -354,6 +354,8 @@ func TestSyntheticMonitorTCPResource(t *testing.T) { }) } +// TODO: icmp and browser + func testMonitorConfig(id, cfg, name string) (string, string) { resourceId := "elasticstack_kibana_synthetics_monitor." + id diff --git a/internal/kibana/synthetics/schema.go b/internal/kibana/synthetics/schema.go index 2f8267a4b..5adfc438d 100644 --- a/internal/kibana/synthetics/schema.go +++ b/internal/kibana/synthetics/schema.go @@ -62,22 +62,37 @@ type tfTCPMonitorFieldsV0 struct { ProxyUseLocalResolver types.Bool `tfsdk:"proxy_use_local_resolver"` } +type tfICMPMonitorFieldsV0 struct { + Host types.String `tfsdk:"host"` + Wait types.Int64 `tfsdk:"wait"` +} + +type tfBrowserMonitorFieldsV0 struct { + InlineScript types.String `tfsdk:"inline_script"` + Screenshots types.String `tfsdk:"screenshots"` + SyntheticsArgs []types.String `tfsdk:"synthetics_args"` + IgnoreHttpsErrors types.Bool `tfsdk:"ignore_https_errors"` + PlaywrightOptions jsontypes.Normalized `tfsdk:"playwright_options"` +} + type tfModelV0 struct { - ID types.String `tfsdk:"id"` - Name types.String `tfsdk:"name"` - SpaceID types.String `tfsdk:"space_id"` - Schedule types.Int64 `tfsdk:"schedule"` - Locations []types.String `tfsdk:"locations"` - PrivateLocations []types.String `tfsdk:"private_locations"` - Enabled types.Bool `tfsdk:"enabled"` - Tags []types.String `tfsdk:"tags"` - Alert *tfAlertConfigV0 `tfsdk:"alert"` - APMServiceName types.String `tfsdk:"service_name"` - TimeoutSeconds types.Int64 `tfsdk:"timeout"` - HTTP *tfHTTPMonitorFieldsV0 `tfsdk:"http"` - TCP *tfTCPMonitorFieldsV0 `tfsdk:"tcp"` - Params jsontypes.Normalized `tfsdk:"params"` - RetestOnFailure types.Bool `tfsdk:"retest_on_failure"` + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + SpaceID types.String `tfsdk:"space_id"` + Schedule types.Int64 `tfsdk:"schedule"` + Locations []types.String `tfsdk:"locations"` + PrivateLocations []types.String `tfsdk:"private_locations"` + Enabled types.Bool `tfsdk:"enabled"` + Tags []types.String `tfsdk:"tags"` + Alert *tfAlertConfigV0 `tfsdk:"alert"` + APMServiceName types.String `tfsdk:"service_name"` + TimeoutSeconds types.Int64 `tfsdk:"timeout"` + HTTP *tfHTTPMonitorFieldsV0 `tfsdk:"http"` + TCP *tfTCPMonitorFieldsV0 `tfsdk:"tcp"` + ICMP *tfICMPMonitorFieldsV0 `tfsdk:"icmp"` + Browser *tfBrowserMonitorFieldsV0 `tfsdk:"browser"` + Params jsontypes.Normalized `tfsdk:"params"` + RetestOnFailure types.Bool `tfsdk:"retest_on_failure"` } func GetCompositeId(id string) (*clients.CompositeId, diag.Diagnostics) { @@ -165,9 +180,11 @@ func monitorConfigSchema() schema.Schema { Optional: true, MarkdownDescription: "The monitor timeout in seconds, monitor will fail if it doesn’t complete within this time. Default: `16`", }, - "params": jsonObjectSchema("Monitor parameters"), - "http": httpMonitorFieldsSchema(), - "tcp": tcpMonitorFieldsSchema(), + "params": jsonObjectSchema("Monitor parameters"), + "http": httpMonitorFieldsSchema(), + "tcp": tcpMonitorFieldsSchema(), + "icmp": icmpMonitorFieldsSchema(), + "browser": browserMonitorFieldsSchema(), "retest_on_failure": schema.BoolAttribute{ Optional: true, MarkdownDescription: "Enable or disable retesting when a monitor fails. By default, monitors are automatically retested if the monitor goes from \"up\" to \"down\". If the result of the retest is also \"down\", an error will be created, and if configured, an alert sent. Then the monitor will resume running according to the defined schedule. Using retest_on_failure can reduce noise related to transient problems. Default: `true`.", @@ -176,6 +193,55 @@ func monitorConfigSchema() schema.Schema { } } +func browserMonitorFieldsSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + Optional: true, + MarkdownDescription: "Browser Monitor specific fields", + Attributes: map[string]schema.Attribute{ + "inline_script": schema.StringAttribute{ + Optional: false, + Required: true, + MarkdownDescription: "The inline script.", + }, + "screenshots": schema.StringAttribute{ + Optional: true, + MarkdownDescription: "Controls the behavior of the screenshots feature.", + Validators: []validator.String{ + stringvalidator.OneOf("on", "off", "only-on-failure"), + }, + }, + "synthetics_args": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + MarkdownDescription: "Synthetics agent CLI arguments.", + }, + "ignore_https_errors": schema.BoolAttribute{ + Optional: true, + MarkdownDescription: "Whether to ignore HTTPS errors.", + }, + "playwright_options": jsonObjectSchema("Playwright options."), + }, + } +} + +func icmpMonitorFieldsSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + Optional: true, + MarkdownDescription: "ICMP Monitor specific fields", + Attributes: map[string]schema.Attribute{ + "host": schema.StringAttribute{ + Optional: false, + Required: true, + MarkdownDescription: "Host to ping; it can be an IP address or a hostname.", + }, + "wait": schema.Int64Attribute{ + Optional: true, + MarkdownDescription: " Wait time in seconds. Default: `1`", + }, + }, + } +} + func jsonObjectSchema(doc string) schema.Attribute { return schema.StringAttribute{ Optional: true, @@ -414,6 +480,8 @@ func (v *tfModelV0) toModelV0(api *kbapi.SyntheticsMonitor) (*tfModelV0, error) var http *tfHTTPMonitorFieldsV0 var tcp *tfTCPMonitorFieldsV0 + var icmp *tfICMPMonitorFieldsV0 + var browser *tfBrowserMonitorFieldsV0 switch mType := api.Type; mType { case kbapi.Http: @@ -428,6 +496,18 @@ func (v *tfModelV0) toModelV0(api *kbapi.SyntheticsMonitor) (*tfModelV0, error) tcp = v.TCP } tcp, err = tcp.toTfTCPMonitorFieldsV0(api) + case kbapi.Icmp: + icmp = &tfICMPMonitorFieldsV0{} + if v.ICMP != nil { + icmp = v.ICMP + } + icmp, err = icmp.toTfICMPMonitorFieldsV0(api) + case kbapi.Browser: + browser = &tfBrowserMonitorFieldsV0{} + if v.Browser != nil { + browser = v.Browser + } + browser, err = browser.toTfIBrowserMonitorFieldsV0(api) default: err = fmt.Errorf("unsupported monitor type: %s", mType) } @@ -464,6 +544,8 @@ func (v *tfModelV0) toModelV0(api *kbapi.SyntheticsMonitor) (*tfModelV0, error) Params: params, HTTP: http, TCP: tcp, + ICMP: icmp, + Browser: browser, RetestOnFailure: v.RetestOnFailure, }, nil } @@ -488,6 +570,43 @@ func (v *tfTCPMonitorFieldsV0) toTfTCPMonitorFieldsV0(api *kbapi.SyntheticsMonit }, nil } +func (v *tfICMPMonitorFieldsV0) toTfICMPMonitorFieldsV0(api *kbapi.SyntheticsMonitor) (*tfICMPMonitorFieldsV0, error) { + wait, err := stringToInt64(string(api.Wait)) + if err != nil { + return nil, err + } + return &tfICMPMonitorFieldsV0{ + Host: types.StringValue(api.Host), + Wait: types.Int64Value(wait), + }, nil +} + +func (v *tfBrowserMonitorFieldsV0) toTfIBrowserMonitorFieldsV0(api *kbapi.SyntheticsMonitor) (*tfBrowserMonitorFieldsV0, error) { + + playwrightOptions, err := toNormalizedValue(api.PlaywrightOptions) + if err != nil { + return nil, err + } + + syntheticsArgs := v.SyntheticsArgs + if api.SyntheticsArgs != nil { + syntheticsArgs = StringSliceValue(api.SyntheticsArgs) + } + + inlineScript := v.InlineScript + if api.InlineScript != "" { + inlineScript = types.StringValue(api.InlineScript) + } + + return &tfBrowserMonitorFieldsV0{ + InlineScript: inlineScript, + Screenshots: types.StringValue(api.Screenshots), + SyntheticsArgs: syntheticsArgs, + IgnoreHttpsErrors: types.BoolPointerValue(api.IgnoreHttpsErrors), + PlaywrightOptions: playwrightOptions, + }, nil +} + func (v *tfHTTPMonitorFieldsV0) toTfHTTPMonitorFieldsV0(api *kbapi.SyntheticsMonitor) (*tfHTTPMonitorFieldsV0, error) { var err error @@ -572,6 +691,10 @@ func (v *tfModelV0) toMonitorFields() (kbapi.MonitorFields, diag.Diagnostics) { return v.toHttpMonitorFields() } else if v.TCP != nil { return v.toTCPMonitorFields(), dg + } else if v.ICMP != nil { + return v.toICMPMonitorFields(), dg + } else if v.Browser != nil { + return v.toBrowserMonitorFields() } dg.AddError("Unsupported monitor type config", "one of http,tcp monitor fields is required") @@ -606,6 +729,14 @@ func (v *tfModelV0) toSyntheticsMonitorConfig() (*kbapi.SyntheticsMonitorConfig, }, diag.Diagnostics{} //dg } +func tfInt64ToString(v types.Int64) string { + res := "" + if !v.IsUnknown() && !v.IsNull() { // handle omitempty case + return strconv.FormatInt(v.ValueInt64(), 10) + } + return res +} + func (v *tfModelV0) toHttpMonitorFields() (kbapi.MonitorFields, diag.Diagnostics) { proxyHeaders, dg := toJsonObject(v.HTTP.ProxyHeader) if dg.HasError() { @@ -619,11 +750,7 @@ func (v *tfModelV0) toHttpMonitorFields() (kbapi.MonitorFields, diag.Diagnostics if dg.HasError() { return nil, dg } - maxRedirects := "" - if !v.HTTP.MaxRedirects.IsUnknown() && !v.HTTP.MaxRedirects.IsNull() { // handle omitempty case - maxRedirects = strconv.FormatInt(v.HTTP.MaxRedirects.ValueInt64(), 10) - - } + maxRedirects := tfInt64ToString(v.HTTP.MaxRedirects) return kbapi.HTTPMonitorFields{ Url: v.HTTP.URL.ValueString(), SslVerificationMode: v.HTTP.SslVerificationMode.ValueString(), @@ -653,6 +780,27 @@ func (v *tfModelV0) toTCPMonitorFields() kbapi.MonitorFields { } } +func (v *tfModelV0) toICMPMonitorFields() kbapi.MonitorFields { + return kbapi.ICMPMonitorFields{ + Host: v.ICMP.Host.ValueString(), + Wait: tfInt64ToString(v.ICMP.Wait), + } +} + +func (v *tfModelV0) toBrowserMonitorFields() (kbapi.MonitorFields, diag.Diagnostics) { + playwrightOptions, dg := toJsonObject(v.Browser.PlaywrightOptions) + if dg.HasError() { + return nil, dg + } + return kbapi.BrowserMonitorFields{ + InlineScript: v.Browser.InlineScript.ValueString(), + Screenshots: kbapi.ScreenshotOption(v.Browser.Screenshots.ValueString()), + SyntheticsArgs: ValueStringSlice(v.Browser.SyntheticsArgs), + IgnoreHttpsErrors: v.Browser.IgnoreHttpsErrors.ValueBoolPointer(), + PlaywrightOptions: playwrightOptions, + }, diag.Diagnostics{} //dg +} + func Map[T, U any](ts []T, f func(T) U) []U { var us []U for _, v := range ts { diff --git a/internal/kibana/synthetics/schema_test.go b/internal/kibana/synthetics/schema_test.go index a6a160e19..30ddf22e3 100644 --- a/internal/kibana/synthetics/schema_test.go +++ b/internal/kibana/synthetics/schema_test.go @@ -76,6 +76,45 @@ func TestToModelV0(t *testing.T) { }, }, }, + { + name: "ICMP monitor empty data", + input: kbapi.SyntheticsMonitor{ + Type: kbapi.Icmp, + }, + expected: tfModelV0{ + ID: types.StringValue("/"), + Name: types.StringValue(""), + SpaceID: types.StringValue(""), + Schedule: types.Int64Value(0), + APMServiceName: types.StringValue(""), + TimeoutSeconds: types.Int64Value(0), + Params: jsontypes.NewNormalizedValue("null"), + ICMP: &tfICMPMonitorFieldsV0{ + Host: types.StringValue(""), + Wait: types.Int64Value(0), + }, + }, + }, + { + name: "Browser monitor empty data", + input: kbapi.SyntheticsMonitor{ + Type: kbapi.Browser, + }, + expected: tfModelV0{ + ID: types.StringValue("/"), + Name: types.StringValue(""), + SpaceID: types.StringValue(""), + Schedule: types.Int64Value(0), + APMServiceName: types.StringValue(""), + TimeoutSeconds: types.Int64Value(0), + Params: jsontypes.NewNormalizedValue("null"), + Browser: &tfBrowserMonitorFieldsV0{ + InlineScript: types.StringValue(""), + Screenshots: types.StringValue(""), + PlaywrightOptions: jsontypes.NewNormalizedValue("null"), + }, + }, + }, { name: "HTTP monitor", input: kbapi.SyntheticsMonitor{ @@ -199,6 +238,110 @@ func TestToModelV0(t *testing.T) { }, }, }, + { + name: "ICMP monitor", + input: kbapi.SyntheticsMonitor{ + Id: "test-id-icmp", + Name: "test-name-icmp", + Namespace: "default", + Enabled: tBool, + Alert: &kbapi.MonitorAlertConfig{Status: &kbapi.SyntheticsStatusConfig{Enabled: tBool}}, + Schedule: &kbapi.MonitorScheduleConfig{Number: "5", Unit: "m"}, + Tags: nil, + APMServiceName: "test-service-tcp", + Timeout: json.Number("30"), + Locations: []kbapi.MonitorLocationConfig{ + {Label: "test private location", IsServiceManaged: false}, + }, + Origin: "origin", + Params: kbapi.JsonObject{"param1": "value1"}, + MaxAttempts: 3, + Revision: 1, + Ui: kbapi.JsonObject{"is_tls_enabled": false}, + Type: kbapi.Icmp, + SslVerificationMode: "full", + SslSupportedProtocols: []string{"TLSv1.2", "TLSv1.3"}, + ProxyUrl: "http://proxy.com", + Host: "example.com:9200", + Wait: "30", + }, + expected: tfModelV0{ + ID: types.StringValue("default/test-id-icmp"), + Name: types.StringValue("test-name-icmp"), + SpaceID: types.StringValue("default"), + Schedule: types.Int64Value(5), + Locations: nil, + PrivateLocations: []types.String{types.StringValue("test private location")}, + Enabled: types.BoolPointerValue(tBool), + Tags: nil, + Alert: &tfAlertConfigV0{Status: &tfStatusConfigV0{Enabled: types.BoolPointerValue(tBool)}}, + APMServiceName: types.StringValue("test-service-tcp"), + TimeoutSeconds: types.Int64Value(30), + Params: jsontypes.NewNormalizedValue(`{"param1":"value1"}`), + ICMP: &tfICMPMonitorFieldsV0{ + Host: types.StringValue("example.com:9200"), + Wait: types.Int64Value(30), + }, + }, + }, + { + name: "Browser monitor", + input: kbapi.SyntheticsMonitor{ + Id: "test-id-browser", + Name: "test-name-browser", + Namespace: "default", + Enabled: tBool, + Alert: &kbapi.MonitorAlertConfig{Status: &kbapi.SyntheticsStatusConfig{Enabled: tBool}}, + Schedule: &kbapi.MonitorScheduleConfig{Number: "5", Unit: "m"}, + Tags: nil, + APMServiceName: "test-service-tcp", + Timeout: json.Number("30"), + Locations: []kbapi.MonitorLocationConfig{ + {Label: "test private location", IsServiceManaged: false}, + }, + Origin: "origin", + Params: kbapi.JsonObject{"param1": "value1"}, + MaxAttempts: 3, + Revision: 1, + Ui: kbapi.JsonObject{"is_tls_enabled": false}, + Type: kbapi.Browser, + SslVerificationMode: "full", + SslSupportedProtocols: []string{"TLSv1.2", "TLSv1.3"}, + ProxyUrl: "http://proxy.com", + Screenshots: "off", + IgnoreHttpsErrors: tBool, + InlineScript: `step('Go to https://google.com.co', () => page.goto('https://www.google.com'))`, + SyntheticsArgs: []string{"--no-sandbox", "--disable-setuid-sandbox"}, + PlaywrightOptions: map[string]interface{}{ + "ignoreHTTPSErrors": false, + "httpCredentials": map[string]interface{}{ + "username": "test", + "password": "test", + }, + }, + }, + expected: tfModelV0{ + ID: types.StringValue("default/test-id-browser"), + Name: types.StringValue("test-name-browser"), + SpaceID: types.StringValue("default"), + Schedule: types.Int64Value(5), + Locations: nil, + PrivateLocations: []types.String{types.StringValue("test private location")}, + Enabled: types.BoolPointerValue(tBool), + Tags: nil, + Alert: &tfAlertConfigV0{Status: &tfStatusConfigV0{Enabled: types.BoolPointerValue(tBool)}}, + APMServiceName: types.StringValue("test-service-tcp"), + TimeoutSeconds: types.Int64Value(30), + Params: jsontypes.NewNormalizedValue(`{"param1":"value1"}`), + Browser: &tfBrowserMonitorFieldsV0{ + Screenshots: types.StringValue("off"), + IgnoreHttpsErrors: types.BoolPointerValue(tBool), + InlineScript: types.StringValue(`step('Go to https://google.com.co', () => page.goto('https://www.google.com'))`), + SyntheticsArgs: []types.String{types.StringValue("--no-sandbox"), types.StringValue("--disable-setuid-sandbox")}, + PlaywrightOptions: jsontypes.NewNormalizedValue(`{"httpCredentials":{"password":"test","username":"test"},"ignoreHTTPSErrors":false}`), + }, + }, + }, } for _, tt := range testcases { @@ -236,6 +379,26 @@ func TestToKibanaAPIRequest(t *testing.T) { config: kbapi.SyntheticsMonitorConfig{}, }, }, + { + name: "Empty ICMP monitor", + input: tfModelV0{ + ICMP: &tfICMPMonitorFieldsV0{}, + }, + expected: kibanaAPIRequest{ + fields: kbapi.ICMPMonitorFields{}, + config: kbapi.SyntheticsMonitorConfig{}, + }, + }, + { + name: "Empty Browser monitor", + input: tfModelV0{ + Browser: &tfBrowserMonitorFieldsV0{}, + }, + expected: kibanaAPIRequest{ + fields: kbapi.BrowserMonitorFields{}, + config: kbapi.SyntheticsMonitorConfig{}, + }, + }, { name: "HTTP monitor", input: tfModelV0{ @@ -348,6 +511,98 @@ func TestToKibanaAPIRequest(t *testing.T) { }, }, }, + { + name: "ICMP monitor", + input: tfModelV0{ + ID: types.StringValue("test-id-icmp"), + Name: types.StringValue("test-name-icmp"), + SpaceID: types.StringValue("default"), + Schedule: types.Int64Value(5), + Locations: []types.String{types.StringValue("us_east")}, + PrivateLocations: nil, + Enabled: types.BoolPointerValue(tBool), + Tags: []types.String{types.StringValue("tag1"), types.StringValue("tag2")}, + Alert: &tfAlertConfigV0{Status: &tfStatusConfigV0{Enabled: types.BoolPointerValue(tBool)}}, + APMServiceName: types.StringValue("test-service-tcp"), + TimeoutSeconds: types.Int64Value(30), + Params: jsontypes.NewNormalizedValue(`{"param1":"value1"}`), + ICMP: &tfICMPMonitorFieldsV0{ + Host: types.StringValue("example.com:9200"), + Wait: types.Int64Value(30), + }, + }, + expected: kibanaAPIRequest{ + config: kbapi.SyntheticsMonitorConfig{ + Name: "test-name-icmp", + Schedule: kbapi.MonitorSchedule(5), + Locations: []kbapi.MonitorLocation{"us_east"}, + PrivateLocations: nil, + Enabled: tBool, + Tags: []string{"tag1", "tag2"}, + Alert: &kbapi.MonitorAlertConfig{Status: &kbapi.SyntheticsStatusConfig{Enabled: tBool}}, + APMServiceName: "test-service-tcp", + Namespace: "default", + TimeoutSeconds: 30, + Params: kbapi.JsonObject{"param1": "value1"}, + }, + fields: kbapi.ICMPMonitorFields{ + Host: "example.com:9200", + Wait: "30", + }, + }, + }, + { + name: "Browser monitor", + input: tfModelV0{ + ID: types.StringValue("test-id-browser"), + Name: types.StringValue("test-name-browser"), + SpaceID: types.StringValue("default"), + Schedule: types.Int64Value(5), + Locations: []types.String{types.StringValue("us_east")}, + PrivateLocations: nil, + Enabled: types.BoolPointerValue(tBool), + Tags: []types.String{types.StringValue("tag1"), types.StringValue("tag2")}, + Alert: &tfAlertConfigV0{Status: &tfStatusConfigV0{Enabled: types.BoolPointerValue(tBool)}}, + APMServiceName: types.StringValue("test-service-tcp"), + TimeoutSeconds: types.Int64Value(30), + Params: jsontypes.NewNormalizedValue(`{"param1":"value1"}`), + Browser: &tfBrowserMonitorFieldsV0{ + Screenshots: types.StringValue("off"), + IgnoreHttpsErrors: types.BoolPointerValue(tBool), + InlineScript: types.StringValue(`step('Go to https://google.com.co', () => page.goto('https://www.google.com'))`), + SyntheticsArgs: []types.String{types.StringValue("--no-sandbox"), types.StringValue("--disable-setuid-sandbox")}, + PlaywrightOptions: jsontypes.NewNormalizedValue(`{"httpCredentials":{"password":"test","username":"test"},"ignoreHTTPSErrors":false}`), + }, + }, + expected: kibanaAPIRequest{ + config: kbapi.SyntheticsMonitorConfig{ + Name: "test-name-browser", + Schedule: kbapi.MonitorSchedule(5), + Locations: []kbapi.MonitorLocation{"us_east"}, + PrivateLocations: nil, + Enabled: tBool, + Tags: []string{"tag1", "tag2"}, + Alert: &kbapi.MonitorAlertConfig{Status: &kbapi.SyntheticsStatusConfig{Enabled: tBool}}, + APMServiceName: "test-service-tcp", + Namespace: "default", + TimeoutSeconds: 30, + Params: kbapi.JsonObject{"param1": "value1"}, + }, + fields: kbapi.BrowserMonitorFields{ + Screenshots: "off", + IgnoreHttpsErrors: tBool, + InlineScript: `step('Go to https://google.com.co', () => page.goto('https://www.google.com'))`, + SyntheticsArgs: []string{"--no-sandbox", "--disable-setuid-sandbox"}, + PlaywrightOptions: map[string]interface{}{ + "ignoreHTTPSErrors": false, + "httpCredentials": map[string]interface{}{ + "username": "test", + "password": "test", + }, + }, + }, + }, + }, } for _, tt := range testcases { @@ -433,6 +688,32 @@ func TestToModelV0MergeAttributes(t *testing.T) { }, }, }, + { + name: "Browser monitor", + state: tfModelV0{ + Browser: &tfBrowserMonitorFieldsV0{ + InlineScript: types.StringValue("aaa"), + SyntheticsArgs: []types.String{types.StringValue("aaa"), types.StringValue("bbb")}, + }, + }, + input: kbapi.SyntheticsMonitor{ + Type: kbapi.Browser, + }, + expected: tfModelV0{ + ID: types.StringValue("/"), + Name: types.StringValue(""), + SpaceID: types.StringValue(""), + Schedule: types.Int64Value(0), + APMServiceName: types.StringValue(""), + TimeoutSeconds: types.Int64Value(0), + Browser: &tfBrowserMonitorFieldsV0{ + InlineScript: types.StringValue("aaa"), + SyntheticsArgs: []types.String{types.StringValue("aaa"), types.StringValue("bbb")}, + Screenshots: types.StringValue(""), + PlaywrightOptions: jsontypes.NewNormalizedValue("null"), + }, + }, + }, } for _, tt := range testcases { From 3f11e7cb918c01902fdcca89b1a8334ddd6b6a73 Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak Date: Sat, 14 Sep 2024 13:21:36 +0200 Subject: [PATCH 3/7] add tests and adjust to API behaviour --- CHANGELOG.md | 1 + docs/resources/kibana_synthetics_monitor.md | 5 +- internal/kibana/synthetics/acc_test.go | 265 +++++++++++++++++++- internal/kibana/synthetics/resource.go | 3 +- internal/kibana/synthetics/schema.go | 21 +- internal/kibana/synthetics/schema_test.go | 7 +- 6 files changed, 289 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d84909d93..443155405 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Add the `Frequency` field to the Create Rule API ([#753](https://github.com/elastic/terraform-provider-elasticstack/pull/753)) - Prevent a provider panic when the repository referenced in an `elasticstack_elasticsearch_snapshot_repository` does not exist ([#758](https://github.com/elastic/terraform-provider-elasticstack/pull/758)) - Add support for `remote_indicies` to `elasticstack_elasticsearch_security_api_key` (#766)[https://github.com/elastic/terraform-provider-elasticstack/pull/766] +- Add support for `icmp` and `browser` monitor types to `elasticstack_kibana_synthetics_monitor` resource (#772)[https://github.com/elastic/terraform-provider-elasticstack/pull/772] ## [0.11.6] - 2024-08-20 diff --git a/docs/resources/kibana_synthetics_monitor.md b/docs/resources/kibana_synthetics_monitor.md index c56a1ee0b..5e7110f97 100644 --- a/docs/resources/kibana_synthetics_monitor.md +++ b/docs/resources/kibana_synthetics_monitor.md @@ -14,11 +14,12 @@ See [API docs](https://www.elastic.co/guide/en/kibana/current/add-monitor-api.ht ## Supported monitor types * `http` * `tcp` + * `icmp` + * `browser` **NOTE:** Due-to nature of partial update API, reset values to defaults is not supported. In case you would like to reset an optional monitor value, please set it explicitly or delete and create new monitor. - ## Example Usage ```terraform @@ -186,4 +187,4 @@ terraform import elasticstack_kibana_synthetics_monitor.my_monitor / page.goto('https://www.google.com'))"), + ), + }, + // ImportState testing - kibana doesn't return required parameter inline_script for browser monitor, so import state is not supported till the fix + /* { + SkipFunc: versionutils.CheckIfVersionIsUnsupported(minKibanaVersion), + ResourceName: browserMonitorId, + ImportState: true, + ImportStateVerify: true, + Config: config, + }, + */// Update and Read browser monitor + { + SkipFunc: versionutils.CheckIfVersionIsUnsupported(minKibanaVersion), + ResourceName: browserMonitorId, + Config: configUpdated, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet(browserMonitorId, "id"), + resource.TestCheckResourceAttr(browserMonitorId, "name", "TestBrowserMonitorResource Updated - "+name), + resource.TestCheckResourceAttr(browserMonitorId, "space_id", "testacc"), + resource.TestCheckResourceAttr(browserMonitorId, "schedule", "10"), + resource.TestCheckResourceAttr(browserMonitorId, "private_locations.#", "1"), + resource.TestCheckResourceAttrSet(browserMonitorId, "private_locations.0"), + resource.TestCheckResourceAttr(browserMonitorId, "enabled", "false"), + resource.TestCheckResourceAttr(browserMonitorId, "tags.#", "3"), + resource.TestCheckResourceAttr(browserMonitorId, "tags.0", "c"), + resource.TestCheckResourceAttr(browserMonitorId, "tags.1", "d"), + resource.TestCheckResourceAttr(browserMonitorId, "tags.2", "e"), + resource.TestCheckResourceAttr(browserMonitorId, "alert.status.enabled", "true"), + resource.TestCheckResourceAttr(browserMonitorId, "alert.tls.enabled", "false"), + resource.TestCheckResourceAttr(browserMonitorId, "service_name", "test apm service"), + resource.TestCheckResourceAttr(browserMonitorId, "timeout", "30"), + resource.TestCheckResourceAttr(browserMonitorId, "browser.inline_script", "step('Go to https://google.de', () => page.goto('https://www.google.de'))"), + resource.TestCheckResourceAttr(browserMonitorId, "browser.synthetics_args.#", "2"), + resource.TestCheckResourceAttr(browserMonitorId, "browser.synthetics_args.0", "--no-sandbox"), + resource.TestCheckResourceAttr(browserMonitorId, "browser.synthetics_args.1", "--disable-setuid-sandbox"), + resource.TestCheckResourceAttr(browserMonitorId, "browser.screenshots", "off"), + resource.TestCheckResourceAttr(browserMonitorId, "browser.ignore_https_errors", "true"), + resource.TestCheckResourceAttr(browserMonitorId, "browser.playwright_options", `{"httpCredentials":{"password":"test","username":"test"},"ignoreHTTPSErrors":false}`), + resource.TestCheckNoResourceAttr(browserMonitorId, "http"), + resource.TestCheckNoResourceAttr(browserMonitorId, "icmp"), + resource.TestCheckNoResourceAttr(browserMonitorId, "tcp"), + ), + }, + // Delete testing automatically occurs in TestCase + + }, + }) +} func testMonitorConfig(id, cfg, name string) (string, string) { diff --git a/internal/kibana/synthetics/resource.go b/internal/kibana/synthetics/resource.go index 1925ff521..33df23985 100644 --- a/internal/kibana/synthetics/resource.go +++ b/internal/kibana/synthetics/resource.go @@ -55,7 +55,8 @@ func (r *Resource) ConfigValidators(ctx context.Context) []resource.ConfigValida resourcevalidator.ExactlyOneOf( path.MatchRoot("http"), path.MatchRoot("tcp"), - // other monitor config types: icmp, browser + path.MatchRoot("icmp"), + path.MatchRoot("browser"), ), resourcevalidator.AtLeastOneOf( path.MatchRoot("locations"), diff --git a/internal/kibana/synthetics/schema.go b/internal/kibana/synthetics/schema.go index 5adfc438d..89b96fa49 100644 --- a/internal/kibana/synthetics/schema.go +++ b/internal/kibana/synthetics/schema.go @@ -11,7 +11,10 @@ import ( "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" @@ -209,6 +212,8 @@ func browserMonitorFieldsSchema() schema.Attribute { Validators: []validator.String{ stringvalidator.OneOf("on", "off", "only-on-failure"), }, + Computed: true, + Default: stringdefault.StaticString("on"), }, "synthetics_args": schema.ListAttribute{ ElementType: types.StringType, @@ -218,6 +223,8 @@ func browserMonitorFieldsSchema() schema.Attribute { "ignore_https_errors": schema.BoolAttribute{ Optional: true, MarkdownDescription: "Whether to ignore HTTPS errors.", + Computed: true, + Default: booldefault.StaticBool(false), }, "playwright_options": jsonObjectSchema("Playwright options."), }, @@ -237,6 +244,8 @@ func icmpMonitorFieldsSchema() schema.Attribute { "wait": schema.Int64Attribute{ Optional: true, MarkdownDescription: " Wait time in seconds. Default: `1`", + Default: int64default.StaticInt64(1), + Computed: true, }, }, } @@ -294,6 +303,8 @@ func httpMonitorFieldsSchema() schema.Attribute { "max_redirects": schema.Int64Attribute{ Optional: true, MarkdownDescription: "The maximum number of redirects to follow. Default: `0`", + Default: int64default.StaticInt64(0), + Computed: true, }, "mode": schema.StringAttribute{ Optional: true, @@ -583,9 +594,13 @@ func (v *tfICMPMonitorFieldsV0) toTfICMPMonitorFieldsV0(api *kbapi.SyntheticsMon func (v *tfBrowserMonitorFieldsV0) toTfIBrowserMonitorFieldsV0(api *kbapi.SyntheticsMonitor) (*tfBrowserMonitorFieldsV0, error) { - playwrightOptions, err := toNormalizedValue(api.PlaywrightOptions) - if err != nil { - return nil, err + var err error + playwrightOptions := v.PlaywrightOptions + if api.PlaywrightOptions != nil { + playwrightOptions, err = toNormalizedValue(api.PlaywrightOptions) + if err != nil { + return nil, err + } } syntheticsArgs := v.SyntheticsArgs diff --git a/internal/kibana/synthetics/schema_test.go b/internal/kibana/synthetics/schema_test.go index 30ddf22e3..f91dbd2f8 100644 --- a/internal/kibana/synthetics/schema_test.go +++ b/internal/kibana/synthetics/schema_test.go @@ -707,10 +707,9 @@ func TestToModelV0MergeAttributes(t *testing.T) { APMServiceName: types.StringValue(""), TimeoutSeconds: types.Int64Value(0), Browser: &tfBrowserMonitorFieldsV0{ - InlineScript: types.StringValue("aaa"), - SyntheticsArgs: []types.String{types.StringValue("aaa"), types.StringValue("bbb")}, - Screenshots: types.StringValue(""), - PlaywrightOptions: jsontypes.NewNormalizedValue("null"), + InlineScript: types.StringValue("aaa"), + SyntheticsArgs: []types.String{types.StringValue("aaa"), types.StringValue("bbb")}, + Screenshots: types.StringValue(""), }, }, }, From 3b87b55d0428a950aef8cd227875bc86496555fd Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak Date: Sat, 14 Sep 2024 13:23:40 +0200 Subject: [PATCH 4/7] docs --- docs/resources/kibana_synthetics_monitor.md | 3 ++- templates/resources/kibana_synthetics_monitor.md.tmpl | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/resources/kibana_synthetics_monitor.md b/docs/resources/kibana_synthetics_monitor.md index 5e7110f97..4ab1908bc 100644 --- a/docs/resources/kibana_synthetics_monitor.md +++ b/docs/resources/kibana_synthetics_monitor.md @@ -20,6 +20,7 @@ See [API docs](https://www.elastic.co/guide/en/kibana/current/add-monitor-api.ht **NOTE:** Due-to nature of partial update API, reset values to defaults is not supported. In case you would like to reset an optional monitor value, please set it explicitly or delete and create new monitor. + ## Example Usage ```terraform @@ -187,4 +188,4 @@ terraform import elasticstack_kibana_synthetics_monitor.my_monitor / Date: Sat, 14 Sep 2024 13:24:15 +0200 Subject: [PATCH 5/7] formatting --- internal/kibana/synthetics/acc_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/kibana/synthetics/acc_test.go b/internal/kibana/synthetics/acc_test.go index c7baa21ec..3034ff000 100644 --- a/internal/kibana/synthetics/acc_test.go +++ b/internal/kibana/synthetics/acc_test.go @@ -576,7 +576,7 @@ func TestSyntheticMonitorBrowserResource(t *testing.T) { ImportStateVerify: true, Config: config, }, - */// Update and Read browser monitor + */ // Update and Read browser monitor { SkipFunc: versionutils.CheckIfVersionIsUnsupported(minKibanaVersion), ResourceName: browserMonitorId, From 960fdd79912d5f225c5f16be71bd44c8f68c79e3 Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak <57406418+biscout42@users.noreply.github.com> Date: Mon, 16 Sep 2024 10:16:09 +0200 Subject: [PATCH 6/7] Update internal/kibana/synthetics/schema.go Co-authored-by: Toby Brain --- internal/kibana/synthetics/schema.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/kibana/synthetics/schema.go b/internal/kibana/synthetics/schema.go index 89b96fa49..6089d98db 100644 --- a/internal/kibana/synthetics/schema.go +++ b/internal/kibana/synthetics/schema.go @@ -592,7 +592,7 @@ func (v *tfICMPMonitorFieldsV0) toTfICMPMonitorFieldsV0(api *kbapi.SyntheticsMon }, nil } -func (v *tfBrowserMonitorFieldsV0) toTfIBrowserMonitorFieldsV0(api *kbapi.SyntheticsMonitor) (*tfBrowserMonitorFieldsV0, error) { +func (v *tfBrowserMonitorFieldsV0) toTfBrowserMonitorFieldsV0(api *kbapi.SyntheticsMonitor) (*tfBrowserMonitorFieldsV0, error) { var err error playwrightOptions := v.PlaywrightOptions From 28934ed06a28dc1b853815c441ed5ec0dc96e9cf Mon Sep 17 00:00:00 2001 From: Boris Ilyushonak Date: Mon, 16 Sep 2024 10:37:18 +0200 Subject: [PATCH 7/7] remove default for computed values --- internal/kibana/synthetics/schema.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/internal/kibana/synthetics/schema.go b/internal/kibana/synthetics/schema.go index 6089d98db..2d69c285f 100644 --- a/internal/kibana/synthetics/schema.go +++ b/internal/kibana/synthetics/schema.go @@ -11,10 +11,9 @@ import ( "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/resource/schema" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" @@ -212,8 +211,8 @@ func browserMonitorFieldsSchema() schema.Attribute { Validators: []validator.String{ stringvalidator.OneOf("on", "off", "only-on-failure"), }, - Computed: true, - Default: stringdefault.StaticString("on"), + Computed: true, + PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()}, }, "synthetics_args": schema.ListAttribute{ ElementType: types.StringType, @@ -224,7 +223,7 @@ func browserMonitorFieldsSchema() schema.Attribute { Optional: true, MarkdownDescription: "Whether to ignore HTTPS errors.", Computed: true, - Default: booldefault.StaticBool(false), + PlanModifiers: []planmodifier.Bool{boolplanmodifier.UseStateForUnknown()}, }, "playwright_options": jsonObjectSchema("Playwright options."), }, @@ -244,7 +243,7 @@ func icmpMonitorFieldsSchema() schema.Attribute { "wait": schema.Int64Attribute{ Optional: true, MarkdownDescription: " Wait time in seconds. Default: `1`", - Default: int64default.StaticInt64(1), + PlanModifiers: []planmodifier.Int64{int64planmodifier.UseStateForUnknown()}, Computed: true, }, }, @@ -303,7 +302,7 @@ func httpMonitorFieldsSchema() schema.Attribute { "max_redirects": schema.Int64Attribute{ Optional: true, MarkdownDescription: "The maximum number of redirects to follow. Default: `0`", - Default: int64default.StaticInt64(0), + PlanModifiers: []planmodifier.Int64{int64planmodifier.UseStateForUnknown()}, Computed: true, }, "mode": schema.StringAttribute{ @@ -518,7 +517,7 @@ func (v *tfModelV0) toModelV0(api *kbapi.SyntheticsMonitor) (*tfModelV0, error) if v.Browser != nil { browser = v.Browser } - browser, err = browser.toTfIBrowserMonitorFieldsV0(api) + browser, err = browser.toTfBrowserMonitorFieldsV0(api) default: err = fmt.Errorf("unsupported monitor type: %s", mType) }