github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/circonus/resource_circonus_check.go (about) 1 package circonus 2 3 /* 4 * Note to future readers: The `circonus_check` resource is actually a facade for 5 * the check_bundle call. check_bundle is an implementation detail that we mask 6 * over and expose just a "check" even though the "check" is actually a 7 * check_bundle. 8 * 9 * Style note: There are three directions that information flows: 10 * 11 * 1) Terraform Config file into API Objects. *Attr named objects are Config or 12 * Schema attribute names. In this file, all config constants should be 13 * named check*Attr. 14 * 15 * 2) API Objects into Statefile data. api*Attr named constants are parameters 16 * that originate from the API and need to be mapped into the provider's 17 * vernacular. 18 */ 19 20 import ( 21 "fmt" 22 "time" 23 24 "github.com/circonus-labs/circonus-gometrics/api" 25 "github.com/circonus-labs/circonus-gometrics/api/config" 26 "github.com/hashicorp/errwrap" 27 "github.com/hashicorp/terraform/helper/schema" 28 ) 29 30 const ( 31 // circonus_check.* global resource attribute names 32 checkActiveAttr = "active" 33 checkCAQLAttr = "caql" 34 checkCloudWatchAttr = "cloudwatch" 35 checkCollectorAttr = "collector" 36 checkConsulAttr = "consul" 37 checkHTTPAttr = "http" 38 checkHTTPTrapAttr = "httptrap" 39 checkICMPPingAttr = "icmp_ping" 40 checkJSONAttr = "json" 41 checkMetricAttr = "metric" 42 checkMetricLimitAttr = "metric_limit" 43 checkMySQLAttr = "mysql" 44 checkNameAttr = "name" 45 checkNotesAttr = "notes" 46 checkPeriodAttr = "period" 47 checkPostgreSQLAttr = "postgresql" 48 checkStatsdAttr = "statsd" 49 checkTCPAttr = "tcp" 50 checkTagsAttr = "tags" 51 checkTargetAttr = "target" 52 checkTimeoutAttr = "timeout" 53 checkTypeAttr = "type" 54 55 // circonus_check.collector.* resource attribute names 56 checkCollectorIDAttr = "id" 57 58 // circonus_check.metric.* resource attribute names are aliased to 59 // circonus_metric.* resource attributes. 60 61 // circonus_check.metric.* resource attribute names 62 // metricIDAttr = "id" 63 64 // Out parameters for circonus_check 65 checkOutByCollectorAttr = "check_by_collector" 66 checkOutIDAttr = "check_id" 67 checkOutChecksAttr = "checks" 68 checkOutCreatedAttr = "created" 69 checkOutLastModifiedAttr = "last_modified" 70 checkOutLastModifiedByAttr = "last_modified_by" 71 checkOutReverseConnectURLsAttr = "reverse_connect_urls" 72 checkOutCheckUUIDsAttr = "uuids" 73 ) 74 75 const ( 76 // Circonus API constants from their API endpoints 77 apiCheckTypeCAQLAttr apiCheckType = "caql" 78 apiCheckTypeCloudWatchAttr apiCheckType = "cloudwatch" 79 apiCheckTypeConsulAttr apiCheckType = "consul" 80 apiCheckTypeHTTPAttr apiCheckType = "http" 81 apiCheckTypeHTTPTrapAttr apiCheckType = "httptrap" 82 apiCheckTypeICMPPingAttr apiCheckType = "ping_icmp" 83 apiCheckTypeJSONAttr apiCheckType = "json" 84 apiCheckTypeMySQLAttr apiCheckType = "mysql" 85 apiCheckTypePostgreSQLAttr apiCheckType = "postgres" 86 apiCheckTypeStatsdAttr apiCheckType = "statsd" 87 apiCheckTypeTCPAttr apiCheckType = "tcp" 88 ) 89 90 var checkDescriptions = attrDescrs{ 91 checkActiveAttr: "If the check is activate or disabled", 92 checkCAQLAttr: "CAQL check configuration", 93 checkCloudWatchAttr: "CloudWatch check configuration", 94 checkCollectorAttr: "The collector(s) that are responsible for gathering the metrics", 95 checkConsulAttr: "Consul check configuration", 96 checkHTTPAttr: "HTTP check configuration", 97 checkHTTPTrapAttr: "HTTP Trap check configuration", 98 checkICMPPingAttr: "ICMP ping check configuration", 99 checkJSONAttr: "JSON check configuration", 100 checkMetricAttr: "Configuration for a stream of metrics", 101 checkMetricLimitAttr: `Setting a metric_limit will enable all (-1), disable (0), or allow up to the specified limit of metrics for this check ("N+", where N is a positive integer)`, 102 checkMySQLAttr: "MySQL check configuration", 103 checkNameAttr: "The name of the check bundle that will be displayed in the web interface", 104 checkNotesAttr: "Notes about this check bundle", 105 checkPeriodAttr: "The period between each time the check is made", 106 checkPostgreSQLAttr: "PostgreSQL check configuration", 107 checkStatsdAttr: "statsd check configuration", 108 checkTCPAttr: "TCP check configuration", 109 checkTagsAttr: "A list of tags assigned to the check", 110 checkTargetAttr: "The target of the check (e.g. hostname, URL, IP, etc)", 111 checkTimeoutAttr: "The length of time in seconds (and fractions of a second) before the check will timeout if no response is returned to the collector", 112 checkTypeAttr: "The check type", 113 114 checkOutByCollectorAttr: "", 115 checkOutCheckUUIDsAttr: "", 116 checkOutChecksAttr: "", 117 checkOutCreatedAttr: "", 118 checkOutIDAttr: "", 119 checkOutLastModifiedAttr: "", 120 checkOutLastModifiedByAttr: "", 121 checkOutReverseConnectURLsAttr: "", 122 } 123 124 var checkCollectorDescriptions = attrDescrs{ 125 checkCollectorIDAttr: "The ID of the collector", 126 } 127 128 var checkMetricDescriptions = metricDescriptions 129 130 func resourceCheck() *schema.Resource { 131 return &schema.Resource{ 132 Create: checkCreate, 133 Read: checkRead, 134 Update: checkUpdate, 135 Delete: checkDelete, 136 Exists: checkExists, 137 Importer: &schema.ResourceImporter{ 138 State: schema.ImportStatePassthrough, 139 }, 140 141 Schema: convertToHelperSchema(checkDescriptions, map[schemaAttr]*schema.Schema{ 142 checkActiveAttr: &schema.Schema{ 143 Type: schema.TypeBool, 144 Optional: true, 145 Default: true, 146 }, 147 checkCAQLAttr: schemaCheckCAQL, 148 checkCloudWatchAttr: schemaCheckCloudWatch, 149 checkCollectorAttr: &schema.Schema{ 150 Type: schema.TypeSet, 151 Optional: true, 152 MinItems: 1, 153 Elem: &schema.Resource{ 154 Schema: convertToHelperSchema(checkCollectorDescriptions, map[schemaAttr]*schema.Schema{ 155 checkCollectorIDAttr: &schema.Schema{ 156 Type: schema.TypeString, 157 Required: true, 158 ValidateFunc: validateRegexp(checkCollectorIDAttr, config.BrokerCIDRegex), 159 }, 160 }), 161 }, 162 }, 163 checkConsulAttr: schemaCheckConsul, 164 checkHTTPAttr: schemaCheckHTTP, 165 checkHTTPTrapAttr: schemaCheckHTTPTrap, 166 checkJSONAttr: schemaCheckJSON, 167 checkICMPPingAttr: schemaCheckICMPPing, 168 checkMetricAttr: &schema.Schema{ 169 Type: schema.TypeSet, 170 Optional: true, 171 Set: checkMetricChecksum, 172 MinItems: 1, 173 Elem: &schema.Resource{ 174 Schema: convertToHelperSchema(checkMetricDescriptions, map[schemaAttr]*schema.Schema{ 175 metricActiveAttr: &schema.Schema{ 176 Type: schema.TypeBool, 177 Optional: true, 178 Default: true, 179 }, 180 metricNameAttr: &schema.Schema{ 181 Type: schema.TypeString, 182 Required: true, 183 ValidateFunc: validateRegexp(metricNameAttr, `[\S]+`), 184 }, 185 metricTagsAttr: tagMakeConfigSchema(metricTagsAttr), 186 metricTypeAttr: &schema.Schema{ 187 Type: schema.TypeString, 188 Required: true, 189 ValidateFunc: validateMetricType, 190 }, 191 metricUnitAttr: &schema.Schema{ 192 Type: schema.TypeString, 193 Optional: true, 194 Default: metricUnit, 195 ValidateFunc: validateRegexp(metricUnitAttr, metricUnitRegexp), 196 }, 197 }), 198 }, 199 }, 200 checkMetricLimitAttr: &schema.Schema{ 201 Type: schema.TypeInt, 202 Optional: true, 203 Computed: true, 204 ValidateFunc: validateFuncs( 205 validateIntMin(checkMetricLimitAttr, -1), 206 ), 207 }, 208 checkMySQLAttr: schemaCheckMySQL, 209 checkNameAttr: &schema.Schema{ 210 Type: schema.TypeString, 211 Optional: true, 212 Computed: true, 213 }, 214 checkNotesAttr: &schema.Schema{ 215 Type: schema.TypeString, 216 Optional: true, 217 Computed: true, 218 StateFunc: suppressWhitespace, 219 }, 220 checkPeriodAttr: &schema.Schema{ 221 Type: schema.TypeString, 222 Optional: true, 223 Computed: true, 224 StateFunc: normalizeTimeDurationStringToSeconds, 225 ValidateFunc: validateFuncs( 226 validateDurationMin(checkPeriodAttr, defaultCirconusCheckPeriodMin), 227 validateDurationMax(checkPeriodAttr, defaultCirconusCheckPeriodMax), 228 ), 229 }, 230 checkPostgreSQLAttr: schemaCheckPostgreSQL, 231 checkStatsdAttr: schemaCheckStatsd, 232 checkTagsAttr: tagMakeConfigSchema(checkTagsAttr), 233 checkTargetAttr: &schema.Schema{ 234 Type: schema.TypeString, 235 Optional: true, 236 Computed: true, 237 ValidateFunc: validateRegexp(checkTagsAttr, `.+`), 238 }, 239 checkTCPAttr: schemaCheckTCP, 240 checkTimeoutAttr: &schema.Schema{ 241 Type: schema.TypeString, 242 Optional: true, 243 Computed: true, 244 StateFunc: normalizeTimeDurationStringToSeconds, 245 ValidateFunc: validateFuncs( 246 validateDurationMin(checkTimeoutAttr, defaultCirconusTimeoutMin), 247 validateDurationMax(checkTimeoutAttr, defaultCirconusTimeoutMax), 248 ), 249 }, 250 checkTypeAttr: &schema.Schema{ 251 Type: schema.TypeString, 252 Computed: true, 253 Optional: true, 254 ForceNew: true, 255 ValidateFunc: validateCheckType, 256 }, 257 258 // Out parameters 259 checkOutIDAttr: &schema.Schema{ 260 Type: schema.TypeString, 261 Computed: true, 262 }, 263 checkOutByCollectorAttr: &schema.Schema{ 264 Type: schema.TypeMap, 265 Computed: true, 266 Elem: &schema.Schema{ 267 Type: schema.TypeString, 268 }, 269 }, 270 checkOutCheckUUIDsAttr: &schema.Schema{ 271 Type: schema.TypeList, 272 Computed: true, 273 Elem: &schema.Schema{ 274 Type: schema.TypeString, 275 }, 276 }, 277 checkOutChecksAttr: &schema.Schema{ 278 Type: schema.TypeList, 279 Computed: true, 280 Elem: &schema.Schema{ 281 Type: schema.TypeString, 282 }, 283 }, 284 checkOutCreatedAttr: &schema.Schema{ 285 Type: schema.TypeInt, 286 Computed: true, 287 }, 288 checkOutLastModifiedAttr: &schema.Schema{ 289 Type: schema.TypeInt, 290 Computed: true, 291 }, 292 checkOutLastModifiedByAttr: &schema.Schema{ 293 Type: schema.TypeString, 294 Computed: true, 295 }, 296 checkOutReverseConnectURLsAttr: &schema.Schema{ 297 Type: schema.TypeList, 298 Computed: true, 299 Elem: &schema.Schema{ 300 Type: schema.TypeString, 301 }, 302 }, 303 }), 304 } 305 } 306 307 func checkCreate(d *schema.ResourceData, meta interface{}) error { 308 ctxt := meta.(*providerContext) 309 c := newCheck() 310 if err := c.ParseConfig(d); err != nil { 311 return errwrap.Wrapf("error parsing check schema during create: {{err}}", err) 312 } 313 314 if err := c.Create(ctxt); err != nil { 315 return errwrap.Wrapf("error creating check: {{err}}", err) 316 } 317 318 d.SetId(c.CID) 319 320 return checkRead(d, meta) 321 } 322 323 func checkExists(d *schema.ResourceData, meta interface{}) (bool, error) { 324 ctxt := meta.(*providerContext) 325 326 cid := d.Id() 327 cb, err := ctxt.client.FetchCheckBundle(api.CIDType(&cid)) 328 if err != nil { 329 return false, err 330 } 331 332 if cb.CID == "" { 333 return false, nil 334 } 335 336 return true, nil 337 } 338 339 // checkRead pulls data out of the CheckBundle object and stores it into the 340 // appropriate place in the statefile. 341 func checkRead(d *schema.ResourceData, meta interface{}) error { 342 ctxt := meta.(*providerContext) 343 344 cid := d.Id() 345 c, err := loadCheck(ctxt, api.CIDType(&cid)) 346 if err != nil { 347 return err 348 } 349 350 d.SetId(c.CID) 351 352 // Global circonus_check attributes are saved first, followed by the check 353 // type specific attributes handled below in their respective checkRead*(). 354 355 checkIDsByCollector := make(map[string]interface{}, len(c.Checks)) 356 for i, b := range c.Brokers { 357 checkIDsByCollector[b] = c.Checks[i] 358 } 359 360 var checkID string 361 if len(c.Checks) == 1 { 362 checkID = c.Checks[0] 363 } 364 365 metrics := schema.NewSet(checkMetricChecksum, nil) 366 for _, m := range c.Metrics { 367 metricAttrs := map[string]interface{}{ 368 string(metricActiveAttr): metricAPIStatusToBool(m.Status), 369 string(metricNameAttr): m.Name, 370 string(metricTagsAttr): tagsToState(apiToTags(m.Tags)), 371 string(metricTypeAttr): m.Type, 372 string(metricUnitAttr): indirect(m.Units), 373 } 374 375 metrics.Add(metricAttrs) 376 } 377 378 // Write the global circonus_check parameters followed by the check 379 // type-specific parameters. 380 381 d.Set(checkActiveAttr, checkAPIStatusToBool(c.Status)) 382 383 if err := d.Set(checkCollectorAttr, stringListToSet(c.Brokers, checkCollectorIDAttr)); err != nil { 384 return errwrap.Wrapf(fmt.Sprintf("Unable to store check %q attribute: {{err}}", checkCollectorAttr), err) 385 } 386 387 d.Set(checkMetricLimitAttr, c.MetricLimit) 388 d.Set(checkNameAttr, c.DisplayName) 389 d.Set(checkNotesAttr, c.Notes) 390 d.Set(checkPeriodAttr, fmt.Sprintf("%ds", c.Period)) 391 392 if err := d.Set(checkMetricAttr, metrics); err != nil { 393 return errwrap.Wrapf(fmt.Sprintf("Unable to store check %q attribute: {{err}}", checkMetricAttr), err) 394 } 395 396 if err := d.Set(checkTagsAttr, c.Tags); err != nil { 397 return errwrap.Wrapf(fmt.Sprintf("Unable to store check %q attribute: {{err}}", checkTagsAttr), err) 398 } 399 400 d.Set(checkTargetAttr, c.Target) 401 402 { 403 t, _ := time.ParseDuration(fmt.Sprintf("%fs", c.Timeout)) 404 d.Set(checkTimeoutAttr, t.String()) 405 } 406 407 d.Set(checkTypeAttr, c.Type) 408 409 // Last step: parse a check_bundle's config into the statefile. 410 if err := parseCheckTypeConfig(&c, d); err != nil { 411 return errwrap.Wrapf("Unable to parse check config: {{err}}", err) 412 } 413 414 // Out parameters 415 if err := d.Set(checkOutByCollectorAttr, checkIDsByCollector); err != nil { 416 return errwrap.Wrapf(fmt.Sprintf("Unable to store check %q attribute: {{err}}", checkOutByCollectorAttr), err) 417 } 418 419 if err := d.Set(checkOutCheckUUIDsAttr, c.CheckUUIDs); err != nil { 420 return errwrap.Wrapf(fmt.Sprintf("Unable to store check %q attribute: {{err}}", checkOutCheckUUIDsAttr), err) 421 } 422 423 if err := d.Set(checkOutChecksAttr, c.Checks); err != nil { 424 return errwrap.Wrapf(fmt.Sprintf("Unable to store check %q attribute: {{err}}", checkOutChecksAttr), err) 425 } 426 427 if checkID != "" { 428 d.Set(checkOutIDAttr, checkID) 429 } 430 431 d.Set(checkOutCreatedAttr, c.Created) 432 d.Set(checkOutLastModifiedAttr, c.LastModified) 433 d.Set(checkOutLastModifiedByAttr, c.LastModifedBy) 434 435 if err := d.Set(checkOutReverseConnectURLsAttr, c.ReverseConnectURLs); err != nil { 436 return errwrap.Wrapf(fmt.Sprintf("Unable to store check %q attribute: {{err}}", checkOutReverseConnectURLsAttr), err) 437 } 438 439 return nil 440 } 441 442 func checkUpdate(d *schema.ResourceData, meta interface{}) error { 443 ctxt := meta.(*providerContext) 444 c := newCheck() 445 if err := c.ParseConfig(d); err != nil { 446 return err 447 } 448 449 c.CID = d.Id() 450 if err := c.Update(ctxt); err != nil { 451 return errwrap.Wrapf(fmt.Sprintf("unable to update check %q: {{err}}", d.Id()), err) 452 } 453 454 return checkRead(d, meta) 455 } 456 457 func checkDelete(d *schema.ResourceData, meta interface{}) error { 458 ctxt := meta.(*providerContext) 459 460 if _, err := ctxt.client.Delete(d.Id()); err != nil { 461 return errwrap.Wrapf(fmt.Sprintf("unable to delete check %q: {{err}}", d.Id()), err) 462 } 463 464 d.SetId("") 465 466 return nil 467 } 468 469 func checkMetricChecksum(v interface{}) int { 470 m := v.(map[string]interface{}) 471 csum := metricChecksum(m) 472 return csum 473 } 474 475 // ParseConfig reads Terraform config data and stores the information into a 476 // Circonus CheckBundle object. 477 func (c *circonusCheck) ParseConfig(d *schema.ResourceData) error { 478 if v, found := d.GetOk(checkActiveAttr); found { 479 c.Status = checkActiveToAPIStatus(v.(bool)) 480 } 481 482 if v, found := d.GetOk(checkCollectorAttr); found { 483 l := v.(*schema.Set).List() 484 c.Brokers = make([]string, 0, len(l)) 485 486 for _, mapRaw := range l { 487 mapAttrs := mapRaw.(map[string]interface{}) 488 489 if mv, mapFound := mapAttrs[checkCollectorIDAttr]; mapFound { 490 c.Brokers = append(c.Brokers, mv.(string)) 491 } 492 } 493 } 494 495 if v, found := d.GetOk(checkMetricLimitAttr); found { 496 c.MetricLimit = v.(int) 497 } 498 499 if v, found := d.GetOk(checkNameAttr); found { 500 c.DisplayName = v.(string) 501 } 502 503 if v, found := d.GetOk(checkNotesAttr); found { 504 s := v.(string) 505 c.Notes = &s 506 } 507 508 if v, found := d.GetOk(checkPeriodAttr); found { 509 d, err := time.ParseDuration(v.(string)) 510 if err != nil { 511 return errwrap.Wrapf(fmt.Sprintf("unable to parse %q as a duration: {{err}}", checkPeriodAttr), err) 512 } 513 514 c.Period = uint(d.Seconds()) 515 } 516 517 if v, found := d.GetOk(checkMetricAttr); found { 518 metricList := v.(*schema.Set).List() 519 c.Metrics = make([]api.CheckBundleMetric, 0, len(metricList)) 520 521 for _, metricListRaw := range metricList { 522 metricAttrs := metricListRaw.(map[string]interface{}) 523 524 var id string 525 if av, found := metricAttrs[metricIDAttr]; found { 526 id = av.(string) 527 } else { 528 var err error 529 id, err = newMetricID() 530 if err != nil { 531 return errwrap.Wrapf("unable to create a new metric ID: {{err}}", err) 532 } 533 } 534 535 m := newMetric() 536 if err := m.ParseConfigMap(id, metricAttrs); err != nil { 537 return errwrap.Wrapf("unable to parse config: {{err}}", err) 538 } 539 540 c.Metrics = append(c.Metrics, m.CheckBundleMetric) 541 } 542 } 543 544 if v, found := d.GetOk(checkTagsAttr); found { 545 c.Tags = derefStringList(flattenSet(v.(*schema.Set))) 546 } 547 548 if v, found := d.GetOk(checkTargetAttr); found { 549 c.Target = v.(string) 550 } 551 552 if v, found := d.GetOk(checkTimeoutAttr); found { 553 d, err := time.ParseDuration(v.(string)) 554 if err != nil { 555 return errwrap.Wrapf(fmt.Sprintf("unable to parse %q as a duration: {{err}}", checkTimeoutAttr), err) 556 } 557 558 t := float32(d.Seconds()) 559 c.Timeout = t 560 } 561 562 // Last step: parse the individual check types 563 if err := checkConfigToAPI(c, d); err != nil { 564 return errwrap.Wrapf("unable to parse check type: {{err}}", err) 565 } 566 567 if err := c.Fixup(); err != nil { 568 return err 569 } 570 571 if err := c.Validate(); err != nil { 572 return err 573 } 574 575 return nil 576 } 577 578 // checkConfigToAPI parses the Terraform config into the respective per-check 579 // type api.Config attributes. 580 func checkConfigToAPI(c *circonusCheck, d *schema.ResourceData) error { 581 checkTypeParseMap := map[string]func(*circonusCheck, interfaceList) error{ 582 checkCAQLAttr: checkConfigToAPICAQL, 583 checkCloudWatchAttr: checkConfigToAPICloudWatch, 584 checkConsulAttr: checkConfigToAPIConsul, 585 checkHTTPAttr: checkConfigToAPIHTTP, 586 checkHTTPTrapAttr: checkConfigToAPIHTTPTrap, 587 checkICMPPingAttr: checkConfigToAPIICMPPing, 588 checkJSONAttr: checkConfigToAPIJSON, 589 checkMySQLAttr: checkConfigToAPIMySQL, 590 checkPostgreSQLAttr: checkConfigToAPIPostgreSQL, 591 checkStatsdAttr: checkConfigToAPIStatsd, 592 checkTCPAttr: checkConfigToAPITCP, 593 } 594 595 for checkType, fn := range checkTypeParseMap { 596 if listRaw, found := d.GetOk(checkType); found { 597 switch u := listRaw.(type) { 598 case []interface{}: 599 if err := fn(c, u); err != nil { 600 return errwrap.Wrapf(fmt.Sprintf("Unable to parse type %q: {{err}}", string(checkType)), err) 601 } 602 case *schema.Set: 603 if err := fn(c, u.List()); err != nil { 604 return errwrap.Wrapf(fmt.Sprintf("Unable to parse type %q: {{err}}", string(checkType)), err) 605 } 606 default: 607 return fmt.Errorf("PROVIDER BUG: unsupported check type interface: %q", checkType) 608 } 609 } 610 } 611 612 return nil 613 } 614 615 // parseCheckTypeConfig parses an API Config object and stores the result in the 616 // statefile. 617 func parseCheckTypeConfig(c *circonusCheck, d *schema.ResourceData) error { 618 checkTypeConfigHandlers := map[apiCheckType]func(*circonusCheck, *schema.ResourceData) error{ 619 apiCheckTypeCAQLAttr: checkAPIToStateCAQL, 620 apiCheckTypeCloudWatchAttr: checkAPIToStateCloudWatch, 621 apiCheckTypeConsulAttr: checkAPIToStateConsul, 622 apiCheckTypeHTTPAttr: checkAPIToStateHTTP, 623 apiCheckTypeHTTPTrapAttr: checkAPIToStateHTTPTrap, 624 apiCheckTypeICMPPingAttr: checkAPIToStateICMPPing, 625 apiCheckTypeJSONAttr: checkAPIToStateJSON, 626 apiCheckTypeMySQLAttr: checkAPIToStateMySQL, 627 apiCheckTypePostgreSQLAttr: checkAPIToStatePostgreSQL, 628 apiCheckTypeStatsdAttr: checkAPIToStateStatsd, 629 apiCheckTypeTCPAttr: checkAPIToStateTCP, 630 } 631 632 var checkType apiCheckType = apiCheckType(c.Type) 633 fn, ok := checkTypeConfigHandlers[checkType] 634 if !ok { 635 return fmt.Errorf("check type %q not supported", c.Type) 636 } 637 638 if err := fn(c, d); err != nil { 639 return errwrap.Wrapf(fmt.Sprintf("unable to parse the API config for %q: {{err}}", c.Type), err) 640 } 641 642 return nil 643 }