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 }