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