diff --git a/docs/resources/logdna_alert.md b/docs/resources/logdna_alert.md index 55bb8fb..53736d2 100644 --- a/docs/resources/logdna_alert.md +++ b/docs/resources/logdna_alert.md @@ -47,11 +47,14 @@ resource "logdna_alert" "my_alert" { } pagerduty_channel { - immediate = "true" - key = "Your PagerDuty API key goes here" - terminal = "true" - triggerinterval = "15m" - triggerlimit = 15 + immediate = "true" + key = "Your PagerDuty API key goes here" + terminal = "true" + triggerinterval = "15m" + triggerlimit = 15 + autoresolve = true + autoresolvelimit = 10 + autoresolveinterval = "15m" } slack_channel { @@ -135,6 +138,9 @@ The following arguments are supported by `logdna_alert`: - `terminal`: **_string_** _(Optional; Default: `"true"`)_ Whether the Alert will trigger after the `triggerinterval` if the Alert condition is met (e.g., send an Alert after 30s). Valid options are `"true"` and `"false"` for presence Alerts and `"true"` for absence Alerts. - `triggerinterval`: **_string_** _(Optional; Defaults: `"30"` for presence; `"15m"` for absence)_ Interval which the Alert will be looking for presence or absence of log lines. For presence Alerts, valid options are: `30`, `1m`, `5m`, `15m`, `30m`, `1h`, `6h`, `12h`, and `24h`. For absence Alerts, valid options are: `15m`, `30m`, `1h`, `6h`, `12h`, and `24h`. - `triggerlimit`: **_integer (Required)_** Number of lines before the Alert is triggered (e.g. setting a value of `10` for an `absence` Alert would alert you if `10` lines were not seen in the `triggerinterval`). +- `autoresolve`: **_boolean_** Set to true if you want the set a condition to resolve the incident that was raised by this alert. +- `autoresolveinterval`: **_string_** _(Required if autoresolve is set to true)_ Interval of time to aggregate and check # of matched lines against the auto resolve limit. For absence Alerts, valid options are: `30`, `1m`, `5m`, `15m`, `30m`, `1h`, `6h`, `12h`, and `24h`. For presence Alerts, valid options are: `15m`, `30m`, `1h`, `6h`, `12h`, and `24h`. +- `autoresolvelimit`: **_integer_** _(Required if autoresolve is set to true)_ Specify the number of log lines that match the view's filtering and search criteria. When the number of log lines is reached, this incident will be set to resolved in PagerDuty. ### slack_channel diff --git a/docs/resources/logdna_view.md b/docs/resources/logdna_view.md index 411fa32..5f231c1 100644 --- a/docs/resources/logdna_view.md +++ b/docs/resources/logdna_view.md @@ -141,6 +141,9 @@ _Note:_ Any of `*_channel` parameters are not allowed if a `presetid` parameter - `terminal`: **_string_** _(Optional; Default: `"true"`)_ Whether the Alert will trigger after the `triggerinterval` if the Alert condition is met (e.g. send an Alert after 30s). Valid options are `"true"` and `"false"` for presence Alerts, and `"true"` for absence Alerts. - `triggerinterval`: **_string_** _(Optional; Defaults: `"30"` for presence; `"15m"` for absence)_ Interval which the Alert will be looking for presence or absence of log lines. For presence Alerts, valid options are: `30`, `1m`, `5m`, `15m`, `30m`, `1h`, `6h`, `12h`, and `24h`. For absence Alerts, valid options are: `15m`, `30m`, `1h`, `6h`, `12h`, and `24h`. - `triggerlimit`: **_integer (Required)_** Number of lines before the Alert is triggered (e.g. setting a value of `10` for an `absence` Alert would alert you if `10` lines were not seen in the `triggerinterval`). +- `autoresolve`: **_boolean_** Set to true if you want the set a condition to resolve the incident that was raised by this alert. +- `autoresolveinterval`: **_string_** _(Required if autoresolve is set to true)_ Interval of time to aggregate and check # of matched lines against the auto resolve limit. Valid values are: 30 seconds, 1 minute, 5 minutes, 15 minutes, 30 minutes, 1 hour, 6 hours, 12 hours, 24 hours. +- `autoresolvelimit`: **_integer_** _(Required if autoresolve is set to true)_ Specify the number of log lines that match the view's filtering and search criteria. When the number of log lines is reached, this incident will be set to resolved in PagerDuty. ### webhook_channel diff --git a/logdna/common_test.go b/logdna/common_test.go index 3b91ac3..09a3212 100644 --- a/logdna/common_test.go +++ b/logdna/common_test.go @@ -89,6 +89,17 @@ var chnlDefaults = map[string]map[string]string{ "triggerlimit": `15`, "url": `"https://yourwebhook/endpoint"`, }, + "pagerduty_channel_auto": { + "immediate": `"false"`, + "operator": `"presence"`, + "key": `"Your PagerDuty API key goes here"`, + "terminal": `"true"`, + "triggerinterval": `"15m"`, + "triggerlimit": `15`, + "autoresolve": `"true"`, + "autoresolvelimit": `"10"`, + "autoresolveinterval": `"15m"`, + }, } func cloneDefaults(dfts map[string]string) map[string]string { diff --git a/logdna/data_source_alert.go b/logdna/data_source_alert.go index c22a740..631b8f2 100644 --- a/logdna/data_source_alert.go +++ b/logdna/data_source_alert.go @@ -18,6 +18,10 @@ var strSchema = &schema.Schema{ Type: schema.TypeString, Computed: true, } +var boolSchema = &schema.Schema{ + Type: schema.TypeBool, + Computed: true, +} var alertProps = map[string]*schema.Schema{ "immediate": strSchema, "operator": strSchema, @@ -142,6 +146,9 @@ func getAlertSchema(chnl string) map[string]*schema.Schema { schma["url"] = strSchema case "pagerduty": schma["key"] = strSchema + schma["autoresolve"] = boolSchema + schma["autoresolvelimit"] = intSchema + schma["autoresolveinterval"] = strSchema case "webhook": schma["bodytemplate"] = strSchema schma["method"] = strSchema diff --git a/logdna/data_source_alert_test.go b/logdna/data_source_alert_test.go index d54cc61..73b1817 100644 --- a/logdna/data_source_alert_test.go +++ b/logdna/data_source_alert_test.go @@ -23,7 +23,7 @@ func TestDataAlert_BulkChannels(t *testing.T) { pdArgs := map[string]map[string]string{ "pagerduty_channel": cloneDefaults(chnlDefaults["pagerduty_channel"]), - "pagerduty1_channel": cloneDefaults(chnlDefaults["pagerduty_channel"]), + "pagerduty1_channel": cloneDefaults(chnlDefaults["pagerduty_channel_auto"]), } pdsCfg := fmtTestConfigResource("alert", "test", globalPcArgs, alertDefaults, pdArgs, nilLst) @@ -60,8 +60,11 @@ func TestDataAlert_BulkChannels(t *testing.T) { testDataSourceAlertExists("data.logdna_alert.remote"), resource.TestCheckResourceAttr("data.logdna_alert.remote", "name", "test"), resource.TestCheckResourceAttr("data.logdna_alert.remote", "pagerduty_channel.#", "2"), - resource.TestCheckResourceAttr("data.logdna_alert.remote", "pagerduty_channel.0.%", "6"), - resource.TestCheckResourceAttr("data.logdna_alert.remote", "pagerduty_channel.1.%", "6"), + resource.TestCheckResourceAttr("data.logdna_alert.remote", "pagerduty_channel.0.%", "9"), + resource.TestCheckResourceAttr("data.logdna_alert.remote", "pagerduty_channel.1.%", "9"), + resource.TestCheckResourceAttr("data.logdna_alert.remote", "pagerduty_channel.1.autoresolve", "true"), + resource.TestCheckResourceAttr("data.logdna_alert.remote", "pagerduty_channel.1.autoresolvelimit", "10"), + resource.TestCheckResourceAttr("data.logdna_alert.remote", "pagerduty_channel.1.autoresolveinterval", "15m"), resource.TestCheckResourceAttr("data.logdna_alert.remote", "email_channel.#", "0"), resource.TestCheckResourceAttr("data.logdna_alert.remote", "slack_channel.#", "0"), resource.TestCheckResourceAttr("data.logdna_alert.remote", "webhook_channel.#", "0"), @@ -124,7 +127,7 @@ func TestDataSourceAlert_MultipleChannels(t *testing.T) { resource.TestCheckResourceAttr("data.logdna_alert.remote", "email_channel.0.triggerinterval", "15m"), resource.TestCheckResourceAttr("data.logdna_alert.remote", "email_channel.0.triggerlimit", "15"), resource.TestCheckResourceAttr("data.logdna_alert.remote", "pagerduty_channel.#", "1"), - resource.TestCheckResourceAttr("data.logdna_alert.remote", "pagerduty_channel.0.%", "6"), + resource.TestCheckResourceAttr("data.logdna_alert.remote", "pagerduty_channel.0.%", "9"), resource.TestCheckResourceAttr("data.logdna_alert.remote", "pagerduty_channel.0.immediate", "false"), resource.TestCheckResourceAttr("data.logdna_alert.remote", "pagerduty_channel.0.key", "Your PagerDuty API key goes here"), resource.TestCheckResourceAttr("data.logdna_alert.remote", "pagerduty_channel.0.operator", "presence"), diff --git a/logdna/request_types.go b/logdna/request_types.go index 8d9de7e..9ef0499 100644 --- a/logdna/request_types.go +++ b/logdna/request_types.go @@ -31,19 +31,22 @@ type alertRequest struct { } type channelRequest struct { - BodyTemplate map[string]interface{} `json:"bodyTemplate,omitempty"` - Emails []string `json:"emails,omitempty"` - Headers map[string]string `json:"headers,omitempty"` - Immediate string `json:"immediate,omitempty"` - Integration string `json:"integration,omitempty"` - Key string `json:"key,omitempty"` - Method string `json:"method,omitempty"` - Operator string `json:"operator,omitempty"` - Terminal string `json:"terminal,omitempty"` - TriggerInterval string `json:"triggerinterval,omitempty"` - TriggerLimit int `json:"triggerlimit,omitempty"` - Timezone string `json:"timezone,omitempty"` - URL string `json:"url,omitempty"` + BodyTemplate map[string]interface{} `json:"bodyTemplate,omitempty"` + Emails []string `json:"emails,omitempty"` + Headers map[string]string `json:"headers,omitempty"` + Immediate string `json:"immediate,omitempty"` + Integration string `json:"integration,omitempty"` + Key string `json:"key,omitempty"` + Method string `json:"method,omitempty"` + Operator string `json:"operator,omitempty"` + Terminal string `json:"terminal,omitempty"` + TriggerInterval string `json:"triggerinterval,omitempty"` + TriggerLimit int `json:"triggerlimit,omitempty"` + AutoResolve bool `json:"autoresolve,omitempty"` + AutoResolveInterval string `json:"autoresolveinterval,omitempty"` + AutoResolveLimit int `json:"autoresolvelimit,omitempty"` + Timezone string `json:"timezone,omitempty"` + URL string `json:"url,omitempty"` } type categoryRequest struct { @@ -359,13 +362,16 @@ func emailChannelRequest(s map[string]interface{}) channelRequest { func pagerDutyChannelRequest(s map[string]interface{}) channelRequest { c := channelRequest{ - Immediate: s["immediate"].(string), - Integration: PAGERDUTY, - Key: s["key"].(string), - Operator: s["operator"].(string), - Terminal: s["terminal"].(string), - TriggerInterval: s["triggerinterval"].(string), - TriggerLimit: s["triggerlimit"].(int), + Immediate: s["immediate"].(string), + Integration: PAGERDUTY, + Key: s["key"].(string), + Operator: s["operator"].(string), + Terminal: s["terminal"].(string), + TriggerInterval: s["triggerinterval"].(string), + TriggerLimit: s["triggerlimit"].(int), + AutoResolve: s["autoresolve"].(bool), + AutoResolveInterval: s["autoresolveinterval"].(string), + AutoResolveLimit: s["autoresolvelimit"].(int), } return c diff --git a/logdna/resource_alert.go b/logdna/resource_alert.go index 836ac12..f9a6a14 100644 --- a/logdna/resource_alert.go +++ b/logdna/resource_alert.go @@ -252,6 +252,25 @@ func resourceAlert() *schema.Resource { return }, }, + "autoresolve": { + Type: schema.TypeBool, + Optional: true, + }, + "autoresolveinterval": { + Type: schema.TypeString, + Optional: true, + }, + "autoresolvelimit": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: func(val interface{}, key string) (warns []string, errs []error) { + v := val.(int) + if v < 1 || v > 100000 { + errs = append(errs, fmt.Errorf("%q must be between 1 and 100,000 inclusive, got: %d", key, v)) + } + return + }, + }, }, }, }, diff --git a/logdna/resource_alert_test.go b/logdna/resource_alert_test.go index eade13b..d6786ad 100644 --- a/logdna/resource_alert_test.go +++ b/logdna/resource_alert_test.go @@ -125,6 +125,55 @@ func TestAlert_ErrorsPagerDutyChannel(t *testing.T) { }) } +func TestAlert_PagerDutyAutoResolve(t *testing.T) { + chArgs := map[string]map[string]string{"pagerduty_channel": cloneDefaults(chnlDefaults["pagerduty_channel_auto"])} + + iniCfg := fmtTestConfigResource("alert", "new", globalPcArgs, alertDefaults, chArgs, nilLst) + + rsArgs := cloneDefaults(rsDefaults["alert"]) + rsArgs["name"] = `"test2"` + updCfg := fmtTestConfigResource("alert", "new", globalPcArgs, rsArgs, chArgs, nilLst) + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: iniCfg, + Check: resource.ComposeTestCheckFunc( + testResourceExists("alert", "new"), + resource.TestCheckResourceAttr("logdna_alert.new", "name", "test"), + resource.TestCheckResourceAttr("logdna_alert.new", "email_channel.#", "0"), + resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.#", "1"), + resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.%", "9"), + resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.immediate", "false"), + resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.key", "Your PagerDuty API key goes here"), + resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.operator", "presence"), + resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.terminal", "true"), + resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.triggerinterval", "15m"), + resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.triggerlimit", "15"), + resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.autoresolve", "true"), + resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.autoresolvelimit", "10"), + resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.autoresolveinterval", "15m"), + resource.TestCheckResourceAttr("logdna_alert.new", "slack_channel.#", "0"), + resource.TestCheckResourceAttr("logdna_alert.new", "webhook_channel.#", "0"), + ), + }, + { + Config: updCfg, + Check: resource.ComposeTestCheckFunc( + testResourceExists("alert", "new"), + resource.TestCheckResourceAttr("logdna_alert.new", "name", "test2"), + ), + }, + { + ResourceName: "logdna_alert.new", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAlert_ErrorsSlackChannel(t *testing.T) { ulInvd := map[string]map[string]string{"slack_channel": cloneDefaults(chnlDefaults["slack_channel"])} ulInvd["slack_channel"]["url"] = `"this is not a valid url"` @@ -283,8 +332,8 @@ func TestAlert_BulkChannels(t *testing.T) { testResourceExists("alert", "new"), resource.TestCheckResourceAttr("logdna_alert.new", "name", "test"), resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.#", "2"), - resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.%", "6"), - resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.1.%", "6"), + resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.%", "9"), + resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.1.%", "9"), resource.TestCheckResourceAttr("logdna_alert.new", "email_channel.#", "0"), resource.TestCheckResourceAttr("logdna_alert.new", "slack_channel.#", "0"), resource.TestCheckResourceAttr("logdna_alert.new", "webhook_channel.#", "0"), @@ -346,8 +395,9 @@ func TestAlert_MultipleChannels(t *testing.T) { resource.TestCheckResourceAttr("logdna_alert.new", "email_channel.0.triggerinterval", "15m"), resource.TestCheckResourceAttr("logdna_alert.new", "email_channel.0.triggerlimit", "15"), resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.#", "1"), - resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.%", "6"), + resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.%", "9"), resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.immediate", "false"), + resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.autoresolve", "false"), resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.key", "Your PagerDuty API key goes here"), resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.operator", "presence"), resource.TestCheckResourceAttr("logdna_alert.new", "pagerduty_channel.0.terminal", "true"), diff --git a/logdna/resource_view.go b/logdna/resource_view.go index 2b997c2..812940c 100644 --- a/logdna/resource_view.go +++ b/logdna/resource_view.go @@ -327,6 +327,25 @@ func resourceView() *schema.Resource { return }, }, + "autoresolve": { + Type: schema.TypeBool, + Optional: true, + }, + "autoresolveinterval": { + Type: schema.TypeString, + Optional: true, + }, + "autoresolvelimit": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: func(val interface{}, key string) (warns []string, errs []error) { + v := val.(int) + if v < 1 || v > 100000 { + errs = append(errs, fmt.Errorf("%q must be between 1 and 100,000 inclusive, got: %d", key, v)) + } + return + }, + }, }, }, }, diff --git a/logdna/resource_view_test.go b/logdna/resource_view_test.go index 0b6e73f..e493cc3 100644 --- a/logdna/resource_view_test.go +++ b/logdna/resource_view_test.go @@ -326,8 +326,8 @@ func TestView_BulkChannels(t *testing.T) { resource.TestCheckResourceAttr("logdna_view.new", "name", "test"), resource.TestCheckResourceAttr("logdna_view.new", "query", "test"), resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.#", "2"), - resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.0.%", "6"), - resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.1.%", "6"), + resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.0.%", "9"), + resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.1.%", "9"), resource.TestCheckResourceAttr("logdna_view.new", "email_channel.#", "0"), resource.TestCheckResourceAttr("logdna_view.new", "slack_channel.#", "0"), resource.TestCheckResourceAttr("logdna_view.new", "webhook_channel.#", "0"), @@ -368,7 +368,7 @@ func TestView_BulkChannels(t *testing.T) { func TestView_MultipleChannels(t *testing.T) { chArgs := map[string]map[string]string{ "email_channel": cloneDefaults(chnlDefaults["email_channel"]), - "pagerduty_channel": cloneDefaults(chnlDefaults["pagerduty_channel"]), + "pagerduty_channel": cloneDefaults(chnlDefaults["pagerduty_channel_auto"]), "slack_channel": cloneDefaults(chnlDefaults["slack_channel"]), "webhook_channel": cloneDefaults(chnlDefaults["webhook_channel"]), } @@ -446,13 +446,16 @@ func TestView_MultipleChannels(t *testing.T) { resource.TestCheckResourceAttr("logdna_view.new", "email_channel.0.triggerinterval", "15m"), resource.TestCheckResourceAttr("logdna_view.new", "email_channel.0.triggerlimit", "15"), resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.#", "1"), - resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.0.%", "6"), + resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.0.%", "9"), resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.0.immediate", "false"), resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.0.key", "Your PagerDuty API key goes here"), resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.0.operator", "presence"), resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.0.terminal", "true"), resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.0.triggerinterval", "15m"), resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.0.triggerlimit", "15"), + resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.0.autoresolve", "true"), + resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.0.autoresolvelimit", "10"), + resource.TestCheckResourceAttr("logdna_view.new", "pagerduty_channel.0.autoresolveinterval", "15m"), resource.TestCheckResourceAttr("logdna_view.new", "slack_channel.#", "1"), resource.TestCheckResourceAttr("logdna_view.new", "slack_channel.0.%", "6"), resource.TestCheckResourceAttr("logdna_view.new", "slack_channel.0.immediate", "false"), diff --git a/logdna/response_types.go b/logdna/response_types.go index af0019b..3ea8cc2 100644 --- a/logdna/response_types.go +++ b/logdna/response_types.go @@ -49,20 +49,23 @@ type memberResponse struct { // NOTE - Properties with `interface` are due to the APIs returning // some things as strings (PUT/emails) and other times arrays (GET/emails) type channelResponse struct { - AlertID string `json:"alertid,omitempty"` - BodyTemplate string `json:"bodyTemplate,omitempty"` - Emails interface{} `json:"emails,omitempty"` - Headers map[string]string `json:"headers,omitempty"` - Immediate bool `json:"immediate,omitempty"` - Integration string `json:"integration,omitempty"` - Key string `json:"key,omitempty"` - Method string `json:"method,omitempty"` - Operator string `json:"operator,omitempty"` - Terminal bool `json:"terminal,omitempty"` - TriggerInterval interface{} `json:"triggerinterval,omitempty"` - TriggerLimit int `json:"triggerlimit,omitempty"` - Timezone string `json:"timezone,omitempty"` - URL string `json:"url,omitempty"` + AlertID string `json:"alertid,omitempty"` + BodyTemplate string `json:"bodyTemplate,omitempty"` + Emails interface{} `json:"emails,omitempty"` + Headers map[string]string `json:"headers,omitempty"` + Immediate bool `json:"immediate,omitempty"` + Integration string `json:"integration,omitempty"` + Key string `json:"key,omitempty"` + Method string `json:"method,omitempty"` + Operator string `json:"operator,omitempty"` + Terminal bool `json:"terminal,omitempty"` + TriggerInterval interface{} `json:"triggerinterval,omitempty"` + TriggerLimit int `json:"triggerlimit,omitempty"` + Timezone string `json:"timezone,omitempty"` + URL string `json:"url,omitempty"` + AutoResolve bool `json:"autoresolve,omitempty"` + AutoResolveInterval string `json:"autoresolveinterval,omitempty"` + AutoResolveLimit int `json:"autoresolvelimit,omitempty"` } type archiveResponse struct { @@ -213,6 +216,9 @@ func mapChannelPagerDuty(channel *channelResponse) map[string]interface{} { c["terminal"] = strconv.FormatBool(channel.Terminal) c["triggerlimit"] = channel.TriggerLimit c["triggerinterval"] = channel.TriggerInterval + c["autoresolve"] = channel.AutoResolve + c["autoresolveinterval"] = channel.AutoResolveInterval + c["autoresolvelimit"] = channel.AutoResolveLimit return c }