github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/circonus/resource_circonus_check_httptrap.go (about)

     1  package circonus
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  	"strings"
     8  
     9  	"github.com/circonus-labs/circonus-gometrics/api/config"
    10  	"github.com/hashicorp/errwrap"
    11  	"github.com/hashicorp/terraform/helper/hashcode"
    12  	"github.com/hashicorp/terraform/helper/schema"
    13  )
    14  
    15  const (
    16  	// circonus_check.httptrap.* resource attribute names
    17  	checkHTTPTrapAsyncMetricsAttr = "async_metrics"
    18  	checkHTTPTrapSecretAttr       = "secret"
    19  )
    20  
    21  var checkHTTPTrapDescriptions = attrDescrs{
    22  	checkHTTPTrapAsyncMetricsAttr: "Specify whether httptrap metrics are logged immediately or held until the status message is emitted",
    23  	checkHTTPTrapSecretAttr:       "",
    24  }
    25  
    26  var schemaCheckHTTPTrap = &schema.Schema{
    27  	Type:     schema.TypeSet,
    28  	Optional: true,
    29  	MaxItems: 1,
    30  	MinItems: 1,
    31  	Set:      hashCheckHTTPTrap,
    32  	Elem: &schema.Resource{
    33  		Schema: convertToHelperSchema(checkHTTPTrapDescriptions, map[schemaAttr]*schema.Schema{
    34  			checkHTTPTrapAsyncMetricsAttr: &schema.Schema{
    35  				Type:     schema.TypeBool,
    36  				Optional: true,
    37  				Default:  defaultCheckHTTPTrapAsync,
    38  			},
    39  			checkHTTPTrapSecretAttr: &schema.Schema{
    40  				Type:         schema.TypeString,
    41  				Optional:     true,
    42  				Sensitive:    true,
    43  				ValidateFunc: validateRegexp(checkHTTPTrapSecretAttr, `^[a-zA-Z0-9_]+$`),
    44  			},
    45  		}),
    46  	},
    47  }
    48  
    49  // checkAPIToStateHTTPTrap reads the Config data out of circonusCheck.CheckBundle into
    50  // the statefile.
    51  func checkAPIToStateHTTPTrap(c *circonusCheck, d *schema.ResourceData) error {
    52  	httpTrapConfig := make(map[string]interface{}, len(c.Config))
    53  
    54  	// swamp is a sanity check: it must be empty by the time this method returns
    55  	swamp := make(map[config.Key]string, len(c.Config))
    56  	for k, v := range c.Config {
    57  		swamp[k] = v
    58  	}
    59  
    60  	saveBoolConfigToState := func(apiKey config.Key, attrName schemaAttr) {
    61  		if s, ok := c.Config[apiKey]; ok {
    62  			switch s {
    63  			case "true", "on":
    64  				httpTrapConfig[string(attrName)] = true
    65  			case "false", "off":
    66  				httpTrapConfig[string(attrName)] = false
    67  			default:
    68  				log.Printf("PROVIDER BUG: unsupported value %q returned in key %q", s, apiKey)
    69  			}
    70  		}
    71  
    72  		delete(swamp, apiKey)
    73  	}
    74  
    75  	saveStringConfigToState := func(apiKey config.Key, attrName schemaAttr) {
    76  		if s, ok := c.Config[apiKey]; ok {
    77  			httpTrapConfig[string(attrName)] = s
    78  		}
    79  
    80  		delete(swamp, apiKey)
    81  	}
    82  
    83  	saveBoolConfigToState(config.AsyncMetrics, checkHTTPTrapAsyncMetricsAttr)
    84  	saveStringConfigToState(config.Secret, checkHTTPTrapSecretAttr)
    85  
    86  	whitelistedConfigKeys := map[config.Key]struct{}{
    87  		config.ReverseSecretKey: struct{}{},
    88  		config.SubmissionURL:    struct{}{},
    89  	}
    90  
    91  	for k := range swamp {
    92  		if _, ok := whitelistedConfigKeys[k]; ok {
    93  			delete(c.Config, k)
    94  		}
    95  
    96  		if _, ok := whitelistedConfigKeys[k]; !ok {
    97  			log.Printf("[ERROR]: PROVIDER BUG: API Config not empty: %#v", swamp)
    98  		}
    99  	}
   100  
   101  	if err := d.Set(checkHTTPTrapAttr, schema.NewSet(hashCheckHTTPTrap, []interface{}{httpTrapConfig})); err != nil {
   102  		return errwrap.Wrapf(fmt.Sprintf("Unable to store check %q attribute: {{err}}", checkHTTPTrapAttr), err)
   103  	}
   104  
   105  	return nil
   106  }
   107  
   108  // hashCheckHTTPTrap creates a stable hash of the normalized values
   109  func hashCheckHTTPTrap(v interface{}) int {
   110  	m := v.(map[string]interface{})
   111  	b := &bytes.Buffer{}
   112  	b.Grow(defaultHashBufSize)
   113  
   114  	writeBool := func(attrName schemaAttr) {
   115  		if v, ok := m[string(attrName)]; ok {
   116  			fmt.Fprintf(b, "%t", v.(bool))
   117  		}
   118  	}
   119  
   120  	writeString := func(attrName schemaAttr) {
   121  		if v, ok := m[string(attrName)]; ok && v.(string) != "" {
   122  			fmt.Fprint(b, strings.TrimSpace(v.(string)))
   123  		}
   124  	}
   125  
   126  	// Order writes to the buffer using lexically sorted list for easy visual
   127  	// reconciliation with other lists.
   128  	writeBool(checkHTTPTrapAsyncMetricsAttr)
   129  	writeString(checkHTTPTrapSecretAttr)
   130  
   131  	s := b.String()
   132  	return hashcode.String(s)
   133  }
   134  
   135  func checkConfigToAPIHTTPTrap(c *circonusCheck, l interfaceList) error {
   136  	c.Type = string(apiCheckTypeHTTPTrapAttr)
   137  
   138  	// Iterate over all `httptrap` attributes, even though we have a max of 1 in the
   139  	// schema.
   140  	for _, mapRaw := range l {
   141  		httpTrapConfig := newInterfaceMap(mapRaw)
   142  
   143  		if v, found := httpTrapConfig[checkHTTPTrapAsyncMetricsAttr]; found {
   144  			b := v.(bool)
   145  			if b {
   146  				c.Config[config.AsyncMetrics] = fmt.Sprintf("%t", b)
   147  			}
   148  		}
   149  
   150  		if v, found := httpTrapConfig[checkHTTPTrapSecretAttr]; found {
   151  			c.Config[config.Secret] = v.(string)
   152  		}
   153  	}
   154  
   155  	return nil
   156  }