From 4b73ac7abe4681bde7608ab0b77d68e004faa7af Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Mon, 6 Feb 2017 14:53:01 -0800 Subject: [PATCH 01/23] Add the `circonus_agent_self` data source. --- builtin/providers/consul/GNUmakefile | 4 + builtin/providers/consul/attr_writer.go | 14 + builtin/providers/consul/attr_writer_map.go | 77 ++ builtin/providers/consul/attr_writer_state.go | 45 + .../consul/data_source_consul_agent_self.go | 872 ++++++++++++++++++ .../data_source_consul_agent_self_test.go | 53 ++ builtin/providers/consul/resource_provider.go | 3 +- builtin/providers/consul/utils.go | 498 ++++++++++ 8 files changed, 1565 insertions(+), 1 deletion(-) create mode 100644 builtin/providers/consul/GNUmakefile create mode 100644 builtin/providers/consul/attr_writer.go create mode 100644 builtin/providers/consul/attr_writer_map.go create mode 100644 builtin/providers/consul/attr_writer_state.go create mode 100644 builtin/providers/consul/data_source_consul_agent_self.go create mode 100644 builtin/providers/consul/data_source_consul_agent_self_test.go create mode 100644 builtin/providers/consul/utils.go diff --git a/builtin/providers/consul/GNUmakefile b/builtin/providers/consul/GNUmakefile new file mode 100644 index 000000000000..224edfbc4262 --- /dev/null +++ b/builtin/providers/consul/GNUmakefile @@ -0,0 +1,4 @@ +# env TESTARGS='-test.parallel=1 -run TestAccDataConsulAgentSelf_basic' TF_LOG=debug make test +test:: + 2>&1 env \ + make -C ../../.. testacc TEST=./builtin/providers/consul | tee test.log diff --git a/builtin/providers/consul/attr_writer.go b/builtin/providers/consul/attr_writer.go new file mode 100644 index 000000000000..c1e5d4fe405c --- /dev/null +++ b/builtin/providers/consul/attr_writer.go @@ -0,0 +1,14 @@ +package consul + +import "github.com/hashicorp/terraform/helper/schema" + +type _AttrWriter interface { + BackingType() string + + SetBool(_SchemaAttr, bool) error + SetFloat64(_SchemaAttr, float64) error + SetList(_SchemaAttr, []interface{}) error + SetMap(_SchemaAttr, map[string]interface{}) error + SetSet(_SchemaAttr, *schema.Set) error + SetString(_SchemaAttr, string) error +} diff --git a/builtin/providers/consul/attr_writer_map.go b/builtin/providers/consul/attr_writer_map.go new file mode 100644 index 000000000000..f603865013ed --- /dev/null +++ b/builtin/providers/consul/attr_writer_map.go @@ -0,0 +1,77 @@ +package consul + +import ( + "fmt" + "strconv" + "strings" + + "github.com/hashicorp/terraform/helper/schema" +) + +type _AttrWriterMap struct { + m *map[string]interface{} +} + +func _NewMapWriter(m *map[string]interface{}) *_AttrWriterMap { + return &_AttrWriterMap{ + m: m, + } +} + +func (w *_AttrWriterMap) BackingType() string { + return "map" +} + +func (w *_AttrWriterMap) Set(name _SchemaAttr, v interface{}) error { + switch u := v.(type) { + case string: + return w.SetString(name, u) + case float64: + return w.SetFloat64(name, u) + case bool: + return w.SetBool(name, u) + case nil: + return w.SetString(name, "") + default: + panic(fmt.Sprintf("PROVIDER BUG: Set type %T not supported (%#v) for %s ", v, v, name)) + } +} + +func (w *_AttrWriterMap) SetBool(name _SchemaAttr, b bool) error { + (*w.m)[string(name)] = fmt.Sprintf("%t", b) + return nil +} + +func (w *_AttrWriterMap) SetFloat64(name _SchemaAttr, f float64) error { + (*w.m)[string(name)] = strconv.FormatFloat(f, 'g', -1, 64) + return nil +} + +func (w *_AttrWriterMap) SetList(name _SchemaAttr, l []interface{}) error { + panic(fmt.Sprintf("PROVIDER BUG: Cat set a list within a map for %s", name)) + out := make([]string, 0, len(l)) + for i, v := range l { + switch u := v.(type) { + case string: + out[i] = u + default: + panic(fmt.Sprintf("PROVIDER BUG: SetList type %T not supported (%#v)", v, v)) + } + } + + (*w.m)[string(name)] = strings.Join(out, ", ") + return nil +} + +func (w *_AttrWriterMap) SetMap(name _SchemaAttr, m map[string]interface{}) error { + panic(fmt.Sprintf("PROVIDER BUG: Cat set a map within a map for %s", name)) +} + +func (w *_AttrWriterMap) SetSet(name _SchemaAttr, s *schema.Set) error { + panic(fmt.Sprintf("PROVIDER BUG: Cat set a set within a map for %s", name)) +} + +func (w *_AttrWriterMap) SetString(name _SchemaAttr, s string) error { + (*w.m)[string(name)] = s + return nil +} diff --git a/builtin/providers/consul/attr_writer_state.go b/builtin/providers/consul/attr_writer_state.go new file mode 100644 index 000000000000..ab11ce095590 --- /dev/null +++ b/builtin/providers/consul/attr_writer_state.go @@ -0,0 +1,45 @@ +package consul + +import "github.com/hashicorp/terraform/helper/schema" + +type _AttrWriterState struct { + d *schema.ResourceData +} + +func _NewStateWriter(d *schema.ResourceData) *_AttrWriterState { + return &_AttrWriterState{ + d: d, + } +} + +func (w *_AttrWriterState) BackingType() string { + return "state" +} + +func (w *_AttrWriterState) SetBool(name _SchemaAttr, b bool) error { + return _StateSet(w.d, name, b) +} + +func (w *_AttrWriterState) SetID(id string) { + w.d.SetId(id) +} + +func (w *_AttrWriterState) SetFloat64(name _SchemaAttr, f float64) error { + return _StateSet(w.d, name, f) +} + +func (w *_AttrWriterState) SetList(name _SchemaAttr, l []interface{}) error { + return _StateSet(w.d, name, l) +} + +func (w *_AttrWriterState) SetMap(name _SchemaAttr, m map[string]interface{}) error { + return _StateSet(w.d, name, m) +} + +func (w *_AttrWriterState) SetSet(name _SchemaAttr, s *schema.Set) error { + return _StateSet(w.d, name, []interface{}{s}) +} + +func (w *_AttrWriterState) SetString(name _SchemaAttr, s string) error { + return _StateSet(w.d, name, s) +} diff --git a/builtin/providers/consul/data_source_consul_agent_self.go b/builtin/providers/consul/data_source_consul_agent_self.go new file mode 100644 index 000000000000..319b32f2b1f2 --- /dev/null +++ b/builtin/providers/consul/data_source_consul_agent_self.go @@ -0,0 +1,872 @@ +package consul + +import ( + "fmt" + + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform/helper/schema" +) + +const ( + _AgentSelfACLDatacenter _TypeKey = iota + _AgentSelfACLDefaultPolicy + _AgentSelfACLDisableTTL + _AgentSelfACLDownPolicy + _AgentSelfACLEnforceVersion8 + _AgentSelfACLTTL + _AgentSelfAddresses + _AgentSelfAdvertiseAddr + _AgentSelfAdvertiseAddrWAN + _AgentSelfAdvertiseAddrs + _AgentSelfAtlasJoin + _AgentSelfBindAddr + _AgentSelfBootstrap + _AgentSelfBootstrapExpect + _AgentSelfCAFile + _AgentSelfCertFile + _AgentSelfCheckDeregisterIntervalMin + _AgentSelfCheckDisableAnonymousSignature + _AgentSelfCheckDisableRemoteExec + _AgentSelfCheckReapInterval + _AgentSelfCheckUpdateInterval + _AgentSelfClientAddr + _AgentSelfDNSConfig + _AgentSelfDNSRecursors + _AgentSelfDataDir + _AgentSelfDatacenter + _AgentSelfDevMode + _AgentSelfDisableCoordinates + _AgentSelfDisableUpdateCheck + _AgentSelfDomain + _AgentSelfEnableDebug + _AgentSelfEnableSyslog + _AgentSelfEnableUI + _AgentSelfID + _AgentSelfKeyFile + _AgentSelfLeaveOnInt + _AgentSelfLeaveOnTerm + _AgentSelfLogLevel + _AgentSelfName + _AgentSelfPerformance + _AgentSelfPidFile + _AgentSelfPorts + _AgentSelfProtocol + _AgentSelfReconnectTimeoutLAN + _AgentSelfReconnectTimeoutWAN + _AgentSelfRejoinAfterLeave + _AgentSelfRetryJoin + _AgentSelfRetryJoinEC2 + _AgentSelfRetryJoinGCE + _AgentSelfRetryJoinWAN + _AgentSelfRetryMaxAttempts + _AgentSelfRetryMaxAttemptsWAN + _AgentSelfRevision + _AgentSelfSerfLANBindAddr + _AgentSelfSerfWANBindAddr + _AgentSelfServer + _AgentSelfServerName + _AgentSelfSessionTTLMin + _AgentSelfStartJoin + _AgentSelfStartJoinWAN + _AgentSelfSyslogFacility + _AgentSelfTLSMinVersion + _AgentSelfTaggedAddresses + _AgentSelfTelemetry + _AgentSelfTranslateWANAddrs + _AgentSelfUIDir + _AgentSelfUnixSockets + _AgentSelfVerifyIncoming + _AgentSelfVerifyOutgoing + _AgentSelfVerifyServerHostname + _AgentSelfVersion + _AgentSelfVersionPrerelease +) + +const ( + _AgentSelfDNSAllowStale _TypeKey = iota + _AgentSelfDNSMaxStale + _AgentSelfRecursorTimeout + _AgentSelfDNSDisableCompression + _AgentSelfDNSEnableTruncate + _AgentSelfDNSNodeTTL + _AgentSelfDNSOnlyPassing + _AgentSelfDNSUDPAnswerLimit + _AgentSelfServiceTTL +) + +const ( + _AgentSelfPerformanceRaftMultiplier _TypeKey = iota +) + +const ( + _AgentSelfPortsDNS _TypeKey = iota + _AgentSelfPortsHTTP + _AgentSelfPortsHTTPS + _AgentSelfPortsRPC + _AgentSelfPortsSerfLAN + _AgentSelfPortsSerfWAN + _AgentSelfPortsServer +) + +const ( + _AgentSelfTaggedAddressesLAN _TypeKey = iota + _AgentSelfTaggedAddressesWAN +) + +const ( + _AgentSelfTelemetryCirconusAPIApp _TypeKey = iota + _AgentSelfTelemetryCirconusAPIURL + _AgentSelfTelemetryCirconusBrokerID + _AgentSelfTelemetryCirconusBrokerSelectTag + _AgentSelfTelemetryCirconusCheckDisplayName + _AgentSelfTelemetryCirconusCheckForceMetricActiation + _AgentSelfTelemetryCirconusCheckID + _AgentSelfTelemetryCirconusCheckInstanceID + _AgentSelfTelemetryCirconusCheckSearchTag + _AgentSelfTelemetryCirconusCheckSubmissionURL + _AgentSelfTelemetryCirconusCheckTags + _AgentSelfTelemetryCirconusSubmissionInterval + _AgentSelfTelemetryDisableHostname + _AgentSelfTelemetryDogStatsdAddr + _AgentSelfTelemetryDogStatsdTags + _AgentSelfTelemetryStatsdAddr + _AgentSelfTelemetryStatsiteAddr + _AgentSelfTelemetryStatsitePrefix +) + +// Schema for consul's /v1/agent/self endpoint +var _AgentSelfMap = map[_TypeKey]*_TypeEntry{ + _AgentSelfACLDatacenter: { + APIName: "ACLDatacenter", + SchemaName: "acl_datacenter", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfACLDefaultPolicy: { + APIName: "ACLDefaultPolicy", + SchemaName: "acl_default_policy", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfACLDisableTTL: { + APIName: "ACLDisabledTTL", + SchemaName: "acl_disable_ttl", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfACLDownPolicy: { + APIName: "ACLDownPolicy", + SchemaName: "acl_down_policy", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfACLEnforceVersion8: { + APIName: "ACLEnforceVersion8", + SchemaName: "acl_enforce_version_8", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfACLTTL: { + APIName: "ACLTTL", + SchemaName: "acl_ttl", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfAddresses: { + APIName: "Addresses", + SchemaName: "addresses", + Source: _SourceAPIResult, + Type: schema.TypeMap, + }, + _AgentSelfAdvertiseAddr: { + APIName: "AdvertiseAddr", + SchemaName: "advertise_addr", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfAdvertiseAddrs: { + APIName: "AdvertiseAddrs", + SchemaName: "advertise_addrs", + Source: _SourceAPIResult, + Type: schema.TypeMap, + }, + _AgentSelfAdvertiseAddrWAN: { + APIName: "AdvertiseAddrWan", + SchemaName: "advertise_addr_wan", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + // Omitting the following since they've been depreciated: + // + // "AtlasInfrastructure": "", + // "AtlasEndpoint": "", + _AgentSelfAtlasJoin: { + APIName: "AtlasJoin", + SchemaName: "atlas_join", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfBindAddr: { + APIName: "BindAddr", + SchemaName: "bind_addr", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfBootstrap: { + APIName: "Bootstrap", + SchemaName: "bootstrap", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfBootstrapExpect: { + APIName: "BootstrapExpect", + SchemaName: "bootstrap_expect", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfCAFile: { + APIName: "CAFile", + SchemaName: "ca_file", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfCertFile: { + APIName: "CertFile", + SchemaName: "cert_file", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfCheckDeregisterIntervalMin: { + APIName: "CheckDeregisterIntervalMin", + SchemaName: "check_deregister_interval_min", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfCheckDisableAnonymousSignature: { + APIName: "DisableAnonymousSignature", + SchemaName: "disable_anonymous_signature", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfCheckDisableRemoteExec: { + APIName: "DisableRemoteExec", + SchemaName: "disable_remote_exec", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfCheckReapInterval: { + APIName: "CheckReapInterval", + SchemaName: "check_reap_interval", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfCheckUpdateInterval: { + APIName: "CheckUpdateInterval", + SchemaName: "check_update_interval", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfClientAddr: { + APIName: "ClientAddr", + SchemaName: "client_addr", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfDNSConfig: { + APIName: "DNSConfig", + SchemaName: "dns_config", + Source: _SourceAPIResult, + Type: schema.TypeMap, + SetMembers: map[_TypeKey]*_TypeEntry{ + _AgentSelfDNSAllowStale: { + APIName: "AllowStale", + SchemaName: "allow_stale", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfDNSDisableCompression: { + APIName: "DisableCompression", + SchemaName: "disable_compression", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfDNSEnableTruncate: { + APIName: "EnableTruncate", + SchemaName: "enable_truncate", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfDNSMaxStale: { + APIName: "MaxStale", + SchemaName: "max_stale", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfDNSNodeTTL: { + APIName: "NodeTTL", + SchemaName: "node_ttl", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfDNSOnlyPassing: { + APIName: "OnlyPassing", + SchemaName: "only_passing", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfRecursorTimeout: { + APIName: "RecursorTimeout", + SchemaName: "recursor_timeout", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfServiceTTL: { + APIName: "ServiceTTL", + SchemaName: "service_ttl", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfDNSUDPAnswerLimit: { + APIName: "UDPAnswerLimit", + SchemaName: "udp_answer_limit", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + }, + }, + _AgentSelfDataDir: { + APIName: "DataDir", + SchemaName: "data_dir", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfDatacenter: { + APIName: "Datacenter", + SchemaName: "datacenter", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfDevMode: { + APIName: "DevMode", + SchemaName: "dev_mode", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfDisableCoordinates: { + APIName: "DisableCoordinates", + SchemaName: "coordinates", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfDisableUpdateCheck: { + APIName: "DisableUpdateCheck", + SchemaName: "update_check", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfDNSRecursors: { + APIName: "DNSRecursors", + APIAliases: []_APIAttr{"DNSRecursor"}, + SchemaName: "dns_recursors", + Source: _SourceAPIResult, + Type: schema.TypeList, + }, + _AgentSelfDomain: { + APIName: "Domain", + SchemaName: "domain", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfEnableDebug: { + APIName: "EnableDebug", + SchemaName: "debug", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfEnableSyslog: { + APIName: "EnableSyslog", + SchemaName: "syslog", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfEnableUI: { + APIName: "EnableUi", + SchemaName: "ui", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + // "HTTPAPIResponseHeaders": nil, + _AgentSelfID: { + APIName: "NodeID", + SchemaName: "id", + Source: _SourceAPIResult, + Type: schema.TypeString, + ValidateFuncs: []interface{}{ + _ValidateRegexp(`(?i)^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$`), + }, + APITest: _APITestID, + APIToState: _APIToStateID, + }, + _AgentSelfKeyFile: { + APIName: "KeyFile", + SchemaName: "key_file", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfLeaveOnInt: { + APIName: "SkipLeaveOnInt", + SchemaName: "leave_on_int", + Source: _SourceAPIResult, + Type: schema.TypeBool, + APITest: _APITestBool, + APIToState: _NegateBoolToState(_APIToStateBool), + }, + _AgentSelfLeaveOnTerm: { + APIName: "LeaveOnTerm", + SchemaName: "leave_on_term", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfLogLevel: { + APIName: "LogLevel", + SchemaName: "log_level", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfName: { + APIName: "NodeName", + SchemaName: "name", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfPerformance: { + APIName: "Performance", + SchemaName: "performance", + Source: _SourceAPIResult, + Type: schema.TypeMap, + SetMembers: map[_TypeKey]*_TypeEntry{ + _AgentSelfPerformanceRaftMultiplier: { + APIName: "RaftMultiplier", + SchemaName: "raft_multiplier", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + }, + }, + _AgentSelfPidFile: { + APIName: "PidFile", + SchemaName: "pid_file", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfPorts: { + APIName: "Ports", + SchemaName: "ports", + Source: _SourceAPIResult, + Type: schema.TypeMap, + SetMembers: map[_TypeKey]*_TypeEntry{ + _AgentSelfPortsDNS: { + APIName: "DNS", + SchemaName: "dns", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfPortsHTTP: { + APIName: "HTTP", + SchemaName: "http", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfPortsHTTPS: { + APIName: "HTTPS", + SchemaName: "https", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfPortsRPC: { + APIName: "RPC", + SchemaName: "rpc", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfPortsSerfLAN: { + APIName: "SerfLan", + SchemaName: "serf_lan", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfPortsSerfWAN: { + APIName: "SerfWan", + SchemaName: "serf_wan", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfPortsServer: { + APIName: "Server", + SchemaName: "server", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + }, + }, + _AgentSelfProtocol: { + APIName: "Protocol", + SchemaName: "protocol", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfReconnectTimeoutLAN: { + APIName: "ReconnectTimeoutLan", + SchemaName: "reconnect_timeout_lan", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfReconnectTimeoutWAN: { + APIName: "ReconnectTimeoutWan", + SchemaName: "reconnect_timeout_wan", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfRejoinAfterLeave: { + APIName: "RejoinAfterLeave", + SchemaName: "rejoin_after_leave", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + // "RetryIntervalWanRaw": "", + _AgentSelfRetryJoin: { + APIName: "RetryJoin", + SchemaName: "retry_join", + Source: _SourceAPIResult, + Type: schema.TypeList, + }, + _AgentSelfRetryJoinWAN: { + APIName: "RetryJoinWan", + SchemaName: "retry_join_wan", + Source: _SourceAPIResult, + Type: schema.TypeList, + }, + _AgentSelfRetryMaxAttempts: { + APIName: "RetryMaxAttempts", + SchemaName: "retry_max_attempts", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfRetryMaxAttemptsWAN: { + APIName: "RetryMaxAttemptsWan", + SchemaName: "retry_max_attempts_wan", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfRetryJoinEC2: { + APIName: "RetryJoinEC2", + SchemaName: "retry_join_ec2", + Source: _SourceAPIResult, + Type: schema.TypeMap, + }, + _AgentSelfRetryJoinGCE: { + APIName: "RetryJoinGCE", + SchemaName: "retry_join_GCE", + Source: _SourceAPIResult, + Type: schema.TypeMap, + }, + _AgentSelfRevision: { + APIName: "Revision", + SchemaName: "revision", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfSerfLANBindAddr: { + APIName: "SerfLanBindAddr", + SchemaName: "serf_lan_bind_addr", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfSerfWANBindAddr: { + APIName: "SerfWanBindAddr", + SchemaName: "serf_wan_bind_addr", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfServer: { + APIName: "Server", + SchemaName: "server", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfServerName: { + APIName: "ServerName", + SchemaName: "server_name", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfSessionTTLMin: { + APIName: "SessionTTLMin", + SchemaName: "session_ttl_min", + Source: _SourceAPIResult, + Type: schema.TypeFloat, + }, + _AgentSelfStartJoin: { + APIName: "StartJoin", + SchemaName: "start_join", + Source: _SourceAPIResult, + Type: schema.TypeList, + }, + _AgentSelfStartJoinWAN: { + APIName: "StartJoinWan", + SchemaName: "start_join_wan", + Source: _SourceAPIResult, + Type: schema.TypeList, + }, + _AgentSelfSyslogFacility: { + APIName: "SyslogFacility", + SchemaName: "syslog_facility", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTaggedAddresses: { + APIName: "TaggedAddresses", + SchemaName: "tagged_addresses", + Source: _SourceAPIResult, + Type: schema.TypeMap, + SetMembers: map[_TypeKey]*_TypeEntry{ + _AgentSelfTaggedAddressesLAN: { + APIName: "LAN", + SchemaName: "lan", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTaggedAddressesWAN: { + APIName: "WAN", + SchemaName: "wan", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + }, + }, + _AgentSelfTelemetry: { + APIName: "Telemetry", + SchemaName: "telemetry", + Source: _SourceAPIResult, + Type: schema.TypeMap, + SetMembers: map[_TypeKey]*_TypeEntry{ + _AgentSelfTelemetryCirconusAPIApp: { + APIName: "CirconusAPIApp", + SchemaName: "circonus_api_app", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryCirconusAPIURL: { + APIName: "CirconusAPIURL", + SchemaName: "circonus_api_url", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryCirconusBrokerID: { + APIName: "CirconusBrokerID", + SchemaName: "circonus_broker_id", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryCirconusBrokerSelectTag: { + APIName: "CirconusBrokerSelectTag", + SchemaName: "circonus_broker_select_tag", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryCirconusCheckDisplayName: { + APIName: "CirconusCheckDisplayName", + SchemaName: "circonus_check_display_name", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryCirconusCheckForceMetricActiation: { + APIName: "CirconusCheckForceMetricActivation", + SchemaName: "circonus_check_force_metric_activation", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryCirconusCheckID: { + APIName: "CirconusCheckID", + SchemaName: "circonus_check_id", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryCirconusCheckInstanceID: { + APIName: "CirconusCheckInstanceID", + SchemaName: "circonus_check_instance_id", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryCirconusCheckSearchTag: { + APIName: "CirconusCheckSearchTag", + SchemaName: "circonus_check_search_tag", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryCirconusCheckSubmissionURL: { + APIName: "CirconusCheckSubmissionURL", + SchemaName: "circonus_check_submission_url", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryCirconusCheckTags: { + APIName: "CirconusCheckTags", + SchemaName: "circonus_check_tags", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryCirconusSubmissionInterval: { + APIName: "CirconusSubmissionInterval", + SchemaName: "circonus_submission_interval", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryDisableHostname: { + APIName: "DisableHostname", + SchemaName: "disable_hostname", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfTelemetryDogStatsdAddr: { + APIName: "DogStatsdAddr", + SchemaName: "dog_statsd_addr", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryDogStatsdTags: { + APIName: "DogStatsdTags", + SchemaName: "dog_statsd_tags", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryStatsdAddr: { + APIName: "StatsdTags", + SchemaName: "statsd_tags", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryStatsiteAddr: { + APIName: "StatsiteAddr", + SchemaName: "statsite_addr", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTelemetryStatsitePrefix: { + APIName: "StatsitePrefix", + SchemaName: "statsite_prefix", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + }, + }, + _AgentSelfTLSMinVersion: { + APIName: "TLSMinVersion", + SchemaName: "tls_min_version", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfTranslateWANAddrs: { + APIName: "TranslateWanAddrs", + SchemaName: "translate_wan_addrs", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfUIDir: { + APIName: "UiDir", + SchemaName: "ui_dir", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfUnixSockets: { + APIName: "UnixSockets", + SchemaName: "unix_sockets", + Source: _SourceAPIResult, + Type: schema.TypeMap, + }, + _AgentSelfVerifyIncoming: { + APIName: "VerifyIncoming", + SchemaName: "verify_incoming", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfVerifyServerHostname: { + APIName: "VerifyServerHostname", + SchemaName: "verify_server_hostname", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfVerifyOutgoing: { + APIName: "VerifyOutgoing", + SchemaName: "verify_outgoing", + Source: _SourceAPIResult, + Type: schema.TypeBool, + }, + _AgentSelfVersion: { + APIName: "Version", + SchemaName: "version", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + _AgentSelfVersionPrerelease: { + APIName: "VersionPrerelease", + SchemaName: "version_prerelease", + Source: _SourceAPIResult, + Type: schema.TypeString, + }, + // "Watches": nil, +} + +func dataSourceConsulAgentSelf() *schema.Resource { + return &schema.Resource{ + Read: dataSourceConsulAgentSelfRead, + Schema: _TypeEntryMapToSchema(_AgentSelfMap), + } +} + +func dataSourceConsulAgentSelfRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*consulapi.Client) + info, err := client.Agent().Self() + if err != nil { + return err + } + + const _APIAgentConfig = "Config" + cfg, ok := info[_APIAgentConfig] + if !ok { + return fmt.Errorf("No %s info available within provider's agent/self endpoint", _APIAgentConfig) + } + + // TODO(sean@): It'd be nice if this data source had a way of filtering out + // irrelevant data so only the important bits are persisted in the state file. + // Something like an attribute mask or even a regexp of matching schema names + // would be sufficient in the most basic case. Food for thought. + dataSourceWriter := _NewStateWriter(d) + + for k, e := range _AgentSelfMap { + apiTest := e.APITest + if apiTest == nil { + apiTest = e.LookupDefaultTypeHandler().APITest + } + if apiTest == nil { + panic(fmt.Sprintf("PROVIDER BUG: %v missing APITest method", k)) + } + + apiToState := e.APIToState + if apiToState == nil { + apiToState = e.LookupDefaultTypeHandler().APIToState + } + if apiToState == nil { + panic(fmt.Sprintf("PROVIDER BUG: %v missing APIToState method", k)) + } + + if v, ok := apiTest(e, cfg); ok { + if err := apiToState(e, v, dataSourceWriter); err != nil { + return errwrap.Wrapf(fmt.Sprintf("error writing %q's data to state: {{err}}", e.SchemaName), err) + } + } + } + + return nil +} diff --git a/builtin/providers/consul/data_source_consul_agent_self_test.go b/builtin/providers/consul/data_source_consul_agent_self_test.go new file mode 100644 index 000000000000..b52b3f8706db --- /dev/null +++ b/builtin/providers/consul/data_source_consul_agent_self_test.go @@ -0,0 +1,53 @@ +package consul + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccDataConsulAgentSelf_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccDataConsulAgentSelfConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckDataSourceValue("data.consul_agent_self.read", "bootstrap", "false"), + testAccCheckDataSourceValue("data.consul_agent_self.read", "datacenter", "dc1"), + testAccCheckDataSourceValue("data.consul_agent_self.read", "id", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "name", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "server", "true"), + ), + }, + }, + }) +} + +func testAccCheckDataSourceValue(n, attr, val string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rn, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Resource not found") + } + out, ok := rn.Primary.Attributes[attr] + if !ok { + return fmt.Errorf("Attribute '%s' not found: %#v", attr, rn.Primary.Attributes) + } + if val != "" && out != val { + return fmt.Errorf("Attribute '%s' value '%s' != '%s'", attr, out, val) + } + if val == "" && out == "" { + return fmt.Errorf("Attribute '%s' value '%s'", attr, out) + } + return nil + } +} + +const testAccDataConsulAgentSelfConfig = ` +data "consul_agent_self" "read" { +} +` diff --git a/builtin/providers/consul/resource_provider.go b/builtin/providers/consul/resource_provider.go index 2b4d01079b17..4688f543cde6 100644 --- a/builtin/providers/consul/resource_provider.go +++ b/builtin/providers/consul/resource_provider.go @@ -64,7 +64,8 @@ func Provider() terraform.ResourceProvider { }, DataSourcesMap: map[string]*schema.Resource{ - "consul_keys": dataSourceConsulKeys(), + "consul_agent_self": dataSourceConsulAgentSelf(), + "consul_keys": dataSourceConsulKeys(), }, ResourcesMap: map[string]*schema.Resource{ diff --git a/builtin/providers/consul/utils.go b/builtin/providers/consul/utils.go new file mode 100644 index 000000000000..d3594a50ef17 --- /dev/null +++ b/builtin/providers/consul/utils.go @@ -0,0 +1,498 @@ +package consul + +import ( + "bytes" + "fmt" + "regexp" + "sort" + "strconv" + + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform/helper/hashcode" + "github.com/hashicorp/terraform/helper/schema" +) + +// _APIAttr is the type used for constants representing well known keys within +// the API that are transmitted back to a resource over an API. +type _APIAttr string + +// _SchemaAttr is the type used for constants representing well known keys +// within the schema for a resource. +type _SchemaAttr string + +// _SourceFlags represent the ways in which an attribute can be written. Some +// sources are mutually exclusive, yet other flag combinations are composable. +type _SourceFlags int + +// _TypeKey is the lookup mechanism for the generated schema. +type _TypeKey int + +// An array of inputs used as typed arguments and converted from their type into +// function objects that are dynamically constructed and executed. +type _ValidatorInputs []interface{} + +// _ValidateRegexp is a regexp pattern to use to validate schema input. +type _ValidateRegexp string + +const ( + // _SourceUserRequired indicates the parameter must be provided by the user in + // their configuration. + _SourceUserRequired _SourceFlags = 1 << iota + + // _SourceUserOptional indicates the parameter may optionally be specified by + // the user in their configuration. + _SourceUserOptional + + // _SourceAPIResult indicates the parameter may only be set by the return of + // an API call. + _SourceAPIResult +) + +type _TypeEntry struct { + APIName _APIAttr + APIAliases []_APIAttr + Source _SourceFlags + Description string + SchemaName _SchemaAttr + Type schema.ValueType + ValidateFuncs []interface{} + SetMembers map[_TypeKey]*_TypeEntry + + // APITest, if returns true, will call APIToState. The if the value was + // found, the second return parameter will include the value that should be + // set in the state store. + APITest func(*_TypeEntry, map[string]interface{}) (interface{}, bool) + + // APIToState takes the value from APITest and writes it to the _AttrWriter + APIToState func(*_TypeEntry, interface{}, _AttrWriter) error +} + +type _TypeHandlers struct { + APITest func(*_TypeEntry, map[string]interface{}) (interface{}, bool) + APIToState func(*_TypeEntry, interface{}, _AttrWriter) error +} + +var _TypeHandlerLookupMap = map[schema.ValueType]*_TypeHandlers{ + schema.TypeBool: &_TypeHandlers{ + APITest: _APITestBool, + APIToState: _APIToStateBool, + }, + schema.TypeFloat: &_TypeHandlers{ + APITest: _APITestFloat64, + APIToState: _APIToStateFloat64, + }, + schema.TypeList: &_TypeHandlers{ + APITest: _APITestList, + APIToState: _APIToStateList, + }, + schema.TypeMap: &_TypeHandlers{ + APITest: _APITestMap, + APIToState: _APIToStateMap, + }, + schema.TypeSet: &_TypeHandlers{ + APITest: _APITestSet, + APIToState: _APIToStateSet, + }, + schema.TypeString: &_TypeHandlers{ + APITest: _APITestString, + APIToState: _APIToStateString, + }, +} + +func _APITestBool(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) { + v, found := self[string(e.APIName)] + if found { + if b, ok := v.(bool); ok { + return b, true + } else { + panic(fmt.Sprintf("PROVIDER BUG: %q fails bool type assertion", e.SchemaName)) + } + } + + return false, false +} + +func _APITestFloat64(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) { + v, found := self[string(e.APIName)] + if found { + if f, ok := v.(float64); ok { + return f, true + } else { + panic(fmt.Sprintf("PROVIDER BUG: %q fails float64 type assertion", e.SchemaName)) + } + } + return 0.0, false +} + +func _APITestID(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) { + v, _ := _APITestString(e, self) + + // Unconditionally return true so that the call to the APIToState handler can + // return an error. + return v, true +} + +func _APITestList(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) { + names := append([]_APIAttr{e.APIName}, e.APIAliases...) + const defaultListLen = 8 + l := make([]interface{}, 0, defaultListLen) + + var foundName bool + for _, name := range names { + v, found := self[string(name)] + if found { + foundName = true + // TODO(sean@): should make a list writer that normalizes v.(type) to a + // string. For now we only accept strings and lists. + switch u := v.(type) { + case []interface{}: + l = append(l, u...) + case string: + l = append(l, u) + default: + panic(fmt.Sprintf("PROVIDER BUG: %q fails list type assertion", e.SchemaName)) + } + } + } + + if foundName { + return l, true + } + + return []interface{}{}, false +} + +func _APITestMap(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) { + v, found := self[string(e.APIName)] + if found { + if m, ok := v.(map[string]interface{}); ok { + return m, true + } else { + panic(fmt.Sprintf("PROVIDER BUG: %q fails map type assertion", e.SchemaName)) + } + } + return "", false +} + +func _APITestSet(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) { + v, found := self[string(e.APIName)] + if found { + if m, ok := v.(map[string]interface{}); ok { + return m, true + } else { + panic(fmt.Sprintf("PROVIDER BUG: %q fails map type assertion", e.SchemaName)) + } + } + return "", false +} + +func _APITestString(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) { + v, found := self[string(e.APIName)] + if found { + if s, ok := v.(string); ok { + return s, true + } else { + panic(fmt.Sprintf("PROVIDER BUG: %q fails string type assertion", e.SchemaName)) + } + } + return "", false +} + +func _APIToStateBool(e *_TypeEntry, v interface{}, w _AttrWriter) error { + return w.SetBool(e.SchemaName, v.(bool)) +} + +func _APIToStateID(e *_TypeEntry, v interface{}, w _AttrWriter) error { + s, ok := v.(string) + if !ok || len(s) == 0 { + return fmt.Errorf("Unable to set %q's ID to an empty or non-string value: %#v", e.SchemaName, v) + } + + stateWriter, ok := w.(*_AttrWriterState) + if !ok { + return fmt.Errorf("PROVIDER BUG: unable to SetID with a non-_AttrWriterState") + } + + stateWriter.SetID(s) + + return nil +} + +func _APIToStateFloat64(e *_TypeEntry, v interface{}, w _AttrWriter) error { + f, ok := v.(float64) + if !ok { + return fmt.Errorf("PROVIDER BUG: unable to cast %s to a float64", e.SchemaName) + } + + return w.SetFloat64(e.SchemaName, f) +} + +func _APIToStateList(e *_TypeEntry, v interface{}, w _AttrWriter) error { + l, ok := v.([]interface{}) + if !ok { + return fmt.Errorf("PROVIDER BUG: unable to cast %s to a list", e.SchemaName) + } + + return w.SetList(e.SchemaName, l) +} + +func _APIToStateMap(e *_TypeEntry, v interface{}, w _AttrWriter) error { + rawMap, ok := v.(map[string]interface{}) + if !ok { + return fmt.Errorf("PROVIDER BUG: unable to cast %s to a map", e.SchemaName) + } + + m := make(map[string]interface{}, len(rawMap)) + mWriter := _NewMapWriter(&m) + + // Make a lookup map by API Schema Name + var setMembersLen int + if e.SetMembers != nil { + setMembersLen = len(e.SetMembers) + } + apiLookup := make(map[string]*_TypeEntry, setMembersLen) + for _, typeEntry := range e.SetMembers { + apiLookup[string(e.SchemaName)] = typeEntry + } + + for k, v := range rawMap { + var usedSchemaHandler bool + if attrEntry, found := apiLookup[k]; found { + usedSchemaHandler = true + if err := attrEntry.APIToState(e, v, mWriter); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Error calling API to state handler on %s: {{err}}", k), err) + } + } + + if !usedSchemaHandler { + if err := mWriter.Set(_SchemaAttr(k), v); err != nil { + return errwrap.Wrapf("Unable to store map in state: {{err}}", err) + } + } + } + + return w.SetMap(e.SchemaName, m) +} + +func _APIToStateSet(e *_TypeEntry, v interface{}, w _AttrWriter) error { + s, ok := v.([]map[string]interface{}) + if !ok { + return fmt.Errorf("PROVIDER BUG: unable to cast %s to a set", e.SchemaName) + } + + set := schema.NewSet(schema.HashResource(nil), nil) + set.Add(s) + + return w.SetSet(e.SchemaName, set) +} + +func _APIToStateString(e *_TypeEntry, v interface{}, w _AttrWriter) error { + s, ok := v.(string) + if !ok { + return fmt.Errorf("PROVIDER BUG: unable to cast %s to a float64", e.SchemaName) + } + + return w.SetString(e.SchemaName, s) +} + +func _HashMap(in interface{}) int { + return 0 + m, ok := in.(map[string]interface{}) + if !ok { + panic(fmt.Sprintf("PROVIDER BUG: Unable to cast %#v to a map", in)) + } + + keys := make([]string, 0, len(m)) + for k, _ := range m { + keys = append(keys, k) + } + + sort.Strings(keys) + + b := &bytes.Buffer{} + const _DefaultHashBufSize = 4096 + b.Grow(_DefaultHashBufSize) + + for _, k := range keys { + v, found := m[k] + if !found { + panic("PROVIDER BUG: race condition: key should not be missing") + } + + fmt.Fprintf(b, k) + switch u := v.(type) { + case string: + fmt.Fprint(b, u) + case bool: + fmt.Fprintf(b, "%t", u) + case float64: + fmt.Fprint(b, strconv.FormatFloat(u, 'g', -1, 64)) + case int, uint: + fmt.Fprintf(b, "%d", u) + case nil: + default: + panic(fmt.Sprintf("Unsupported type %T in map hasher", v)) + } + } + + return hashcode.String(b.String()) +} + +func _Indirect(v interface{}) interface{} { + switch v.(type) { + case string: + return v + case *string: + p := v.(*string) + if p == nil { + return nil + } + return *p + default: + return v + } +} + +func (e *_TypeEntry) LookupDefaultTypeHandler() *_TypeHandlers { + h, found := _TypeHandlerLookupMap[e.Type] + if !found { + panic(fmt.Sprintf("PROVIDER BUG: unable to lookup %q's type (%#v)", e.SchemaName, e.Type)) + } + + return h +} + +// _NegateBoolToState is a factory function that creates a new function that +// negates whatever the bool is that's passed in as an argument. +func _NegateBoolToState(fn func(*_TypeEntry, interface{}, _AttrWriter) error) func(*_TypeEntry, interface{}, _AttrWriter) error { + return func(e *_TypeEntry, v interface{}, w _AttrWriter) error { + b, ok := v.(bool) + if !ok { + return fmt.Errorf("Unable to type assert non-bool value: %#v", v) + } + + return fn(e, !b, w) + } +} + +// _StateSet sets an attribute based on an attrName. Return an error if the +// Set() to schema.ResourceData fails. +func _StateSet(d *schema.ResourceData, attrName _SchemaAttr, v interface{}) error { + if err := d.Set(string(attrName), _Indirect(v)); err != nil { + return fmt.Errorf("PROVIDER BUG: failed set schema attribute %s to value %#v: %v", attrName, v, err) + } + + return nil +} + +func _TypeEntryMapToSchema(in map[_TypeKey]*_TypeEntry) map[string]*schema.Schema { + out := make(map[string]*schema.Schema, len(in)) + for _, e := range in { + e.Validate() + + attr := &schema.Schema{ + Type: e.Type, + Description: e.Description, + Optional: e.Source&_SourceAPIResult == _SourceAPIResult, + Required: e.Source&_SourceUserRequired == _SourceUserRequired, + Computed: e.Source&_SourceAPIResult == _SourceAPIResult, + ValidateFunc: e.MakeValidationFunc(), + } + + // Fixup the type: use the real type vs a surrogate type + switch e.Type { + case schema.TypeList: + attr.Elem = &schema.Schema{ + Type: schema.TypeString, + } + case schema.TypeSet: + attr.Elem = &schema.Resource{ + Schema: _TypeEntryMapToSchema(e.SetMembers), + } + } + + out[string(e.SchemaName)] = attr + } + + return out +} + +func (e *_TypeEntry) Validate() { + if e.Source&_SourceAPIResult == _SourceAPIResult && e.Type == schema.TypeSet { + panic(fmt.Sprintf("PROVIDER BUG: %s can not be computed and of type Set", e.SchemaName)) + } + + if len(e.SetMembers) != 0 && !(e.Type == schema.TypeSet || e.Type == schema.TypeMap) { + panic(fmt.Sprintf("PROVIDER BUG: %s is not of type Set but has SetMembers set", e.SchemaName)) + } + + if e.Source&(_SourceUserRequired|_SourceAPIResult) == (_SourceUserRequired | _SourceAPIResult) { + panic(fmt.Sprintf("PROVIDER BUG: %#v and %#v are mutually exclusive Source flags", _SourceUserRequired, _SourceAPIResult)) + } +} + +// MakeValidateionFunc takes a list of typed validator inputs from the receiver +// and creates a validation closure that calls each validator in serial until +// either a warning or error is returned from the first validation function. +func (e *_TypeEntry) MakeValidationFunc() func(v interface{}, key string) (warnings []string, errors []error) { + if len(e.ValidateFuncs) == 0 { + return nil + } + + fns := make([]func(v interface{}, key string) (warnings []string, errors []error), len(e.ValidateFuncs)) + for _, v := range e.ValidateFuncs { + switch u := v.(type) { + case _ValidateRegexp: + fns = append(fns, _ValidateRegexpFactory(e, string(u))) + } + } + + return func(v interface{}, key string) (warnings []string, errors []error) { + for _, fn := range fns { + warnings, errors = fn(v, key) + if len(warnings) > 0 || len(errors) > 0 { + break + } + } + return warnings, errors + } +} + +// _ValidateFuncs takes a list of typed validator inputs, creates validation +// functions for each and then runs them in serial until either a warning or +// error is returned from the first validation function. +func _ValidateFuncs(e *_TypeEntry, in ...interface{}) func(v interface{}, key string) (warnings []string, errors []error) { + if len(in) == 0 { + return nil + } + + fns := make([]func(v interface{}, key string) (warnings []string, errors []error), len(in)) + for _, v := range in { + switch v.(type) { + case _ValidateRegexp: + fns = append(fns, _ValidateRegexpFactory(e, v.(string))) + } + } + + return func(v interface{}, key string) (warnings []string, errors []error) { + for _, fn := range fns { + warnings, errors = fn(v, key) + if len(warnings) > 0 || len(errors) > 0 { + break + } + } + return warnings, errors + } +} + +func _ValidateRegexpFactory(e *_TypeEntry, reString string) func(v interface{}, key string) (warnings []string, errors []error) { + re := regexp.MustCompile(reString) + + return func(v interface{}, key string) (warnings []string, errors []error) { + if !re.MatchString(v.(string)) { + errors = append(errors, fmt.Errorf("Invalid %s specified (%q): regexp failed to match string", e.SchemaName, v.(string))) + } + + return warnings, errors + } +} From 77d7e250187185bd1cb56ebb7a3820ef4e832df3 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Mon, 6 Feb 2017 15:13:42 -0800 Subject: [PATCH 02/23] Remove stale code that would never be called at present. --- builtin/providers/consul/attr_writer_map.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/builtin/providers/consul/attr_writer_map.go b/builtin/providers/consul/attr_writer_map.go index f603865013ed..82bab523483a 100644 --- a/builtin/providers/consul/attr_writer_map.go +++ b/builtin/providers/consul/attr_writer_map.go @@ -3,7 +3,6 @@ package consul import ( "fmt" "strconv" - "strings" "github.com/hashicorp/terraform/helper/schema" ) @@ -49,18 +48,6 @@ func (w *_AttrWriterMap) SetFloat64(name _SchemaAttr, f float64) error { func (w *_AttrWriterMap) SetList(name _SchemaAttr, l []interface{}) error { panic(fmt.Sprintf("PROVIDER BUG: Cat set a list within a map for %s", name)) - out := make([]string, 0, len(l)) - for i, v := range l { - switch u := v.(type) { - case string: - out[i] = u - default: - panic(fmt.Sprintf("PROVIDER BUG: SetList type %T not supported (%#v)", v, v)) - } - } - - (*w.m)[string(name)] = strings.Join(out, ", ") - return nil } func (w *_AttrWriterMap) SetMap(name _SchemaAttr, m map[string]interface{}) error { From 7063ee1af2617675b6ec901da11053382a966fc6 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Tue, 7 Feb 2017 14:46:10 -0800 Subject: [PATCH 03/23] Update `github.com/hashicorp/consul/api` to the latest and greatest. --- .../github.com/hashicorp/consul/api/agent.go | 71 +++++++- vendor/github.com/hashicorp/consul/api/api.go | 67 +++++-- .../hashicorp/consul/api/catalog.go | 27 ++- .../github.com/hashicorp/consul/api/health.go | 71 +++++++- vendor/github.com/hashicorp/consul/api/kv.go | 61 +++++-- .../github.com/hashicorp/consul/api/lock.go | 14 +- .../hashicorp/consul/api/operator.go | 163 ++++++++++++++++++ .../hashicorp/consul/api/prepared_query.go | 16 +- .../hashicorp/consul/api/snapshot.go | 47 +++++ vendor/vendor.json | 6 +- 10 files changed, 481 insertions(+), 62 deletions(-) create mode 100644 vendor/github.com/hashicorp/consul/api/operator.go create mode 100644 vendor/github.com/hashicorp/consul/api/snapshot.go diff --git a/vendor/github.com/hashicorp/consul/api/agent.go b/vendor/github.com/hashicorp/consul/api/agent.go index 3df013cc5b9e..1893d1cf359d 100644 --- a/vendor/github.com/hashicorp/consul/api/agent.go +++ b/vendor/github.com/hashicorp/consul/api/agent.go @@ -1,6 +1,7 @@ package api import ( + "bufio" "fmt" ) @@ -62,8 +63,7 @@ type AgentCheckRegistration struct { AgentServiceCheck } -// AgentServiceCheck is used to create an associated -// check for a service +// AgentServiceCheck is used to define a node or service level check type AgentServiceCheck struct { Script string `json:",omitempty"` DockerContainerID string `json:",omitempty"` @@ -74,6 +74,16 @@ type AgentServiceCheck struct { HTTP string `json:",omitempty"` TCP string `json:",omitempty"` Status string `json:",omitempty"` + Notes string `json:",omitempty"` + TLSSkipVerify bool `json:",omitempty"` + + // In Consul 0.7 and later, checks that are associated with a service + // may also contain this optional DeregisterCriticalServiceAfter field, + // which is a timeout in the same Go time format as Interval and TTL. If + // a check is in the critical state for more than this configured value, + // then its associated service (and all of its associated checks) will + // automatically be deregistered. + DeregisterCriticalServiceAfter string `json:",omitempty"` } type AgentServiceChecks []*AgentServiceCheck @@ -107,6 +117,17 @@ func (a *Agent) Self() (map[string]map[string]interface{}, error) { return out, nil } +// Reload triggers a configuration reload for the agent we are connected to. +func (a *Agent) Reload() error { + r := a.c.newRequest("PUT", "/v1/agent/reload") + _, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return err + } + resp.Body.Close() + return nil +} + // NodeName is used to get the node name of the agent func (a *Agent) NodeName() (string, error) { if a.nodeName != "" { @@ -338,6 +359,17 @@ func (a *Agent) Join(addr string, wan bool) error { return nil } +// Leave is used to have the agent gracefully leave the cluster and shutdown +func (a *Agent) Leave() error { + r := a.c.newRequest("PUT", "/v1/agent/leave") + _, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return err + } + resp.Body.Close() + return nil +} + // ForceLeave is used to have the agent eject a failed node func (a *Agent) ForceLeave(node string) error { r := a.c.newRequest("PUT", "/v1/agent/force-leave/"+node) @@ -402,3 +434,38 @@ func (a *Agent) DisableNodeMaintenance() error { resp.Body.Close() return nil } + +// Monitor returns a channel which will receive streaming logs from the agent +// Providing a non-nil stopCh can be used to close the connection and stop the +// log stream +func (a *Agent) Monitor(loglevel string, stopCh chan struct{}, q *QueryOptions) (chan string, error) { + r := a.c.newRequest("GET", "/v1/agent/monitor") + r.setQueryOptions(q) + if loglevel != "" { + r.params.Add("loglevel", loglevel) + } + _, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return nil, err + } + + logCh := make(chan string, 64) + go func() { + defer resp.Body.Close() + + scanner := bufio.NewScanner(resp.Body) + for { + select { + case <-stopCh: + close(logCh) + return + default: + } + if scanner.Scan() { + logCh <- scanner.Text() + } + } + }() + + return logCh, nil +} diff --git a/vendor/github.com/hashicorp/consul/api/api.go b/vendor/github.com/hashicorp/consul/api/api.go index 590b858e1fca..9a59b724cbae 100644 --- a/vendor/github.com/hashicorp/consul/api/api.go +++ b/vendor/github.com/hashicorp/consul/api/api.go @@ -20,6 +20,28 @@ import ( "github.com/hashicorp/go-cleanhttp" ) +const ( + // HTTPAddrEnvName defines an environment variable name which sets + // the HTTP address if there is no -http-addr specified. + HTTPAddrEnvName = "CONSUL_HTTP_ADDR" + + // HTTPTokenEnvName defines an environment variable name which sets + // the HTTP token. + HTTPTokenEnvName = "CONSUL_HTTP_TOKEN" + + // HTTPAuthEnvName defines an environment variable name which sets + // the HTTP authentication header. + HTTPAuthEnvName = "CONSUL_HTTP_AUTH" + + // HTTPSSLEnvName defines an environment variable name which sets + // whether or not to use HTTPS. + HTTPSSLEnvName = "CONSUL_HTTP_SSL" + + // HTTPSSLVerifyEnvName defines an environment variable name which sets + // whether or not to disable certificate checking. + HTTPSSLVerifyEnvName = "CONSUL_HTTP_SSL_VERIFY" +) + // QueryOptions are used to parameterize a query type QueryOptions struct { // Providing a datacenter overwrites the DC provided @@ -52,6 +74,11 @@ type QueryOptions struct { // that node. Setting this to "_agent" will use the agent's node // for the sort. Near string + + // NodeMeta is used to filter results by nodes with the given + // metadata key/value pairs. Currently, only one key/value pair can + // be provided for filtering. + NodeMeta map[string]string } // WriteOptions are used to parameterize a write @@ -80,6 +107,9 @@ type QueryMeta struct { // How long did the request take RequestTime time.Duration + + // Is address translation enabled for HTTP responses on this agent + AddressTranslationEnabled bool } // WriteMeta is used to return meta data about a write @@ -178,15 +208,15 @@ func defaultConfig(transportFn func() *http.Transport) *Config { }, } - if addr := os.Getenv("CONSUL_HTTP_ADDR"); addr != "" { + if addr := os.Getenv(HTTPAddrEnvName); addr != "" { config.Address = addr } - if token := os.Getenv("CONSUL_HTTP_TOKEN"); token != "" { + if token := os.Getenv(HTTPTokenEnvName); token != "" { config.Token = token } - if auth := os.Getenv("CONSUL_HTTP_AUTH"); auth != "" { + if auth := os.Getenv(HTTPAuthEnvName); auth != "" { var username, password string if strings.Contains(auth, ":") { split := strings.SplitN(auth, ":", 2) @@ -202,10 +232,10 @@ func defaultConfig(transportFn func() *http.Transport) *Config { } } - if ssl := os.Getenv("CONSUL_HTTP_SSL"); ssl != "" { + if ssl := os.Getenv(HTTPSSLEnvName); ssl != "" { enabled, err := strconv.ParseBool(ssl) if err != nil { - log.Printf("[WARN] client: could not parse CONSUL_HTTP_SSL: %s", err) + log.Printf("[WARN] client: could not parse %s: %s", HTTPSSLEnvName, err) } if enabled { @@ -213,10 +243,10 @@ func defaultConfig(transportFn func() *http.Transport) *Config { } } - if verify := os.Getenv("CONSUL_HTTP_SSL_VERIFY"); verify != "" { + if verify := os.Getenv(HTTPSSLVerifyEnvName); verify != "" { doVerify, err := strconv.ParseBool(verify) if err != nil { - log.Printf("[WARN] client: could not parse CONSUL_HTTP_SSL_VERIFY: %s", err) + log.Printf("[WARN] client: could not parse %s: %s", HTTPSSLVerifyEnvName, err) } if !doVerify { @@ -330,6 +360,7 @@ type request struct { url *url.URL params url.Values body io.Reader + header http.Header obj interface{} } @@ -355,11 +386,16 @@ func (r *request) setQueryOptions(q *QueryOptions) { r.params.Set("wait", durToMsec(q.WaitTime)) } if q.Token != "" { - r.params.Set("token", q.Token) + r.header.Set("X-Consul-Token", q.Token) } if q.Near != "" { r.params.Set("near", q.Near) } + if len(q.NodeMeta) > 0 { + for key, value := range q.NodeMeta { + r.params.Add("node-meta", key+":"+value) + } + } } // durToMsec converts a duration to a millisecond specified string. If the @@ -399,7 +435,7 @@ func (r *request) setWriteOptions(q *WriteOptions) { r.params.Set("dc", q.Datacenter) } if q.Token != "" { - r.params.Set("token", q.Token) + r.header.Set("X-Consul-Token", q.Token) } } @@ -426,6 +462,7 @@ func (r *request) toHTTP() (*http.Request, error) { req.URL.Host = r.url.Host req.URL.Scheme = r.url.Scheme req.Host = r.url.Host + req.Header = r.header // Setup auth if r.config.HttpAuth != nil { @@ -446,6 +483,7 @@ func (c *Client) newRequest(method, path string) *request { Path: path, }, params: make(map[string][]string), + header: make(http.Header), } if c.config.Datacenter != "" { r.params.Set("dc", c.config.Datacenter) @@ -454,7 +492,7 @@ func (c *Client) newRequest(method, path string) *request { r.params.Set("wait", durToMsec(r.config.WaitTime)) } if c.config.Token != "" { - r.params.Set("token", r.config.Token) + r.header.Set("X-Consul-Token", r.config.Token) } return r } @@ -539,6 +577,15 @@ func parseQueryMeta(resp *http.Response, q *QueryMeta) error { default: q.KnownLeader = false } + + // Parse X-Consul-Translate-Addresses + switch header.Get("X-Consul-Translate-Addresses") { + case "true": + q.AddressTranslationEnabled = true + default: + q.AddressTranslationEnabled = false + } + return nil } diff --git a/vendor/github.com/hashicorp/consul/api/catalog.go b/vendor/github.com/hashicorp/consul/api/catalog.go index 52a00b3043f8..96226f11f897 100644 --- a/vendor/github.com/hashicorp/consul/api/catalog.go +++ b/vendor/github.com/hashicorp/consul/api/catalog.go @@ -1,19 +1,27 @@ package api type Node struct { - Node string - Address string + ID string + Node string + Address string + TaggedAddresses map[string]string + Meta map[string]string } type CatalogService struct { + ID string Node string Address string + TaggedAddresses map[string]string + NodeMeta map[string]string ServiceID string ServiceName string ServiceAddress string ServiceTags []string ServicePort int ServiceEnableTagOverride bool + CreateIndex uint64 + ModifyIndex uint64 } type CatalogNode struct { @@ -22,16 +30,19 @@ type CatalogNode struct { } type CatalogRegistration struct { - Node string - Address string - Datacenter string - Service *AgentService - Check *AgentCheck + ID string + Node string + Address string + TaggedAddresses map[string]string + NodeMeta map[string]string + Datacenter string + Service *AgentService + Check *AgentCheck } type CatalogDeregistration struct { Node string - Address string + Address string // Obsolete. Datacenter string ServiceID string CheckID string diff --git a/vendor/github.com/hashicorp/consul/api/health.go b/vendor/github.com/hashicorp/consul/api/health.go index 5bb403f554f0..8abe2393ad50 100644 --- a/vendor/github.com/hashicorp/consul/api/health.go +++ b/vendor/github.com/hashicorp/consul/api/health.go @@ -2,16 +2,25 @@ package api import ( "fmt" + "strings" ) const ( // HealthAny is special, and is used as a wild card, // not as a specific state. HealthAny = "any" - HealthUnknown = "unknown" HealthPassing = "passing" HealthWarning = "warning" HealthCritical = "critical" + HealthMaint = "maintenance" +) + +const ( + // NodeMaint is the special key set by a node in maintenance mode. + NodeMaint = "_node_maintenance" + + // ServiceMaintPrefix is the prefix for a service in maintenance mode. + ServiceMaintPrefix = "_service_maintenance:" ) // HealthCheck is used to represent a single check @@ -26,11 +35,56 @@ type HealthCheck struct { ServiceName string } +// HealthChecks is a collection of HealthCheck structs. +type HealthChecks []*HealthCheck + +// AggregatedStatus returns the "best" status for the list of health checks. +// Because a given entry may have many service and node-level health checks +// attached, this function determines the best representative of the status as +// as single string using the following heuristic: +// +// maintenance > critical > warning > passing +// +func (c HealthChecks) AggregatedStatus() string { + var passing, warning, critical, maintenance bool + for _, check := range c { + id := string(check.CheckID) + if id == NodeMaint || strings.HasPrefix(id, ServiceMaintPrefix) { + maintenance = true + continue + } + + switch check.Status { + case HealthPassing: + passing = true + case HealthWarning: + warning = true + case HealthCritical: + critical = true + default: + return "" + } + } + + switch { + case maintenance: + return HealthMaint + case critical: + return HealthCritical + case warning: + return HealthWarning + case passing: + return HealthPassing + default: + return HealthPassing + } +} + // ServiceEntry is used for the health service endpoint type ServiceEntry struct { Node *Node Service *AgentService - Checks []*HealthCheck + Checks HealthChecks } // Health can be used to query the Health endpoints @@ -44,7 +98,7 @@ func (c *Client) Health() *Health { } // Node is used to query for checks belonging to a given node -func (h *Health) Node(node string, q *QueryOptions) ([]*HealthCheck, *QueryMeta, error) { +func (h *Health) Node(node string, q *QueryOptions) (HealthChecks, *QueryMeta, error) { r := h.c.newRequest("GET", "/v1/health/node/"+node) r.setQueryOptions(q) rtt, resp, err := requireOK(h.c.doRequest(r)) @@ -57,7 +111,7 @@ func (h *Health) Node(node string, q *QueryOptions) ([]*HealthCheck, *QueryMeta, parseQueryMeta(resp, qm) qm.RequestTime = rtt - var out []*HealthCheck + var out HealthChecks if err := decodeBody(resp, &out); err != nil { return nil, nil, err } @@ -65,7 +119,7 @@ func (h *Health) Node(node string, q *QueryOptions) ([]*HealthCheck, *QueryMeta, } // Checks is used to return the checks associated with a service -func (h *Health) Checks(service string, q *QueryOptions) ([]*HealthCheck, *QueryMeta, error) { +func (h *Health) Checks(service string, q *QueryOptions) (HealthChecks, *QueryMeta, error) { r := h.c.newRequest("GET", "/v1/health/checks/"+service) r.setQueryOptions(q) rtt, resp, err := requireOK(h.c.doRequest(r)) @@ -78,7 +132,7 @@ func (h *Health) Checks(service string, q *QueryOptions) ([]*HealthCheck, *Query parseQueryMeta(resp, qm) qm.RequestTime = rtt - var out []*HealthCheck + var out HealthChecks if err := decodeBody(resp, &out); err != nil { return nil, nil, err } @@ -116,13 +170,12 @@ func (h *Health) Service(service, tag string, passingOnly bool, q *QueryOptions) // State is used to retrieve all the checks in a given state. // The wildcard "any" state can also be used for all checks. -func (h *Health) State(state string, q *QueryOptions) ([]*HealthCheck, *QueryMeta, error) { +func (h *Health) State(state string, q *QueryOptions) (HealthChecks, *QueryMeta, error) { switch state { case HealthAny: case HealthWarning: case HealthCritical: case HealthPassing: - case HealthUnknown: default: return nil, nil, fmt.Errorf("Unsupported state: %v", state) } @@ -138,7 +191,7 @@ func (h *Health) State(state string, q *QueryOptions) ([]*HealthCheck, *QueryMet parseQueryMeta(resp, qm) qm.RequestTime = rtt - var out []*HealthCheck + var out HealthChecks if err := decodeBody(resp, &out); err != nil { return nil, nil, err } diff --git a/vendor/github.com/hashicorp/consul/api/kv.go b/vendor/github.com/hashicorp/consul/api/kv.go index 3dac2583c125..44e06bbb470d 100644 --- a/vendor/github.com/hashicorp/consul/api/kv.go +++ b/vendor/github.com/hashicorp/consul/api/kv.go @@ -11,13 +11,35 @@ import ( // KVPair is used to represent a single K/V entry type KVPair struct { - Key string + // Key is the name of the key. It is also part of the URL path when accessed + // via the API. + Key string + + // CreateIndex holds the index corresponding the creation of this KVPair. This + // is a read-only field. CreateIndex uint64 + + // ModifyIndex is used for the Check-And-Set operations and can also be fed + // back into the WaitIndex of the QueryOptions in order to perform blocking + // queries. ModifyIndex uint64 - LockIndex uint64 - Flags uint64 - Value []byte - Session string + + // LockIndex holds the index corresponding to a lock on this key, if any. This + // is a read-only field. + LockIndex uint64 + + // Flags are any user-defined flags on the key. It is up to the implementer + // to check these values, since Consul does not treat them specially. + Flags uint64 + + // Value is the value for the key. This can be any value, but it will be + // base64 encoded upon transport. + Value []byte + + // Session is a string representing the ID of the session. Any other + // interactions with this key over the same session must specify the same + // session ID. + Session string } // KVPairs is a list of KVPair objects @@ -28,21 +50,21 @@ type KVOp string const ( KVSet KVOp = "set" - KVDelete = "delete" - KVDeleteCAS = "delete-cas" - KVDeleteTree = "delete-tree" - KVCAS = "cas" - KVLock = "lock" - KVUnlock = "unlock" - KVGet = "get" - KVGetTree = "get-tree" - KVCheckSession = "check-session" - KVCheckIndex = "check-index" + KVDelete KVOp = "delete" + KVDeleteCAS KVOp = "delete-cas" + KVDeleteTree KVOp = "delete-tree" + KVCAS KVOp = "cas" + KVLock KVOp = "lock" + KVUnlock KVOp = "unlock" + KVGet KVOp = "get" + KVGetTree KVOp = "get-tree" + KVCheckSession KVOp = "check-session" + KVCheckIndex KVOp = "check-index" ) // KVTxnOp defines a single operation inside a transaction. type KVTxnOp struct { - Verb string + Verb KVOp Key string Value []byte Flags uint64 @@ -70,7 +92,8 @@ func (c *Client) KV() *KV { return &KV{c} } -// Get is used to lookup a single key +// Get is used to lookup a single key. The returned pointer +// to the KVPair will be nil if the key does not exist. func (k *KV) Get(key string, q *QueryOptions) (*KVPair, *QueryMeta, error) { resp, qm, err := k.getInternal(key, nil, q) if err != nil { @@ -133,7 +156,7 @@ func (k *KV) Keys(prefix, separator string, q *QueryOptions) ([]string, *QueryMe } func (k *KV) getInternal(key string, params map[string]string, q *QueryOptions) (*http.Response, *QueryMeta, error) { - r := k.c.newRequest("GET", "/v1/kv/"+key) + r := k.c.newRequest("GET", "/v1/kv/"+strings.TrimPrefix(key, "/")) r.setQueryOptions(q) for param, val := range params { r.params.Set(param, val) @@ -254,7 +277,7 @@ func (k *KV) DeleteTree(prefix string, w *WriteOptions) (*WriteMeta, error) { } func (k *KV) deleteInternal(key string, params map[string]string, q *WriteOptions) (bool, *WriteMeta, error) { - r := k.c.newRequest("DELETE", "/v1/kv/"+key) + r := k.c.newRequest("DELETE", "/v1/kv/"+strings.TrimPrefix(key, "/")) r.setWriteOptions(q) for param, val := range params { r.params.Set(param, val) diff --git a/vendor/github.com/hashicorp/consul/api/lock.go b/vendor/github.com/hashicorp/consul/api/lock.go index 08e8e793108d..9f9845a4325b 100644 --- a/vendor/github.com/hashicorp/consul/api/lock.go +++ b/vendor/github.com/hashicorp/consul/api/lock.go @@ -72,8 +72,9 @@ type LockOptions struct { Key string // Must be set and have write permissions Value []byte // Optional, value to associate with the lock Session string // Optional, created if not specified - SessionName string // Optional, defaults to DefaultLockSessionName - SessionTTL string // Optional, defaults to DefaultLockSessionTTL + SessionOpts *SessionEntry // Optional, options to use when creating a session + SessionName string // Optional, defaults to DefaultLockSessionName (ignored if SessionOpts is given) + SessionTTL string // Optional, defaults to DefaultLockSessionTTL (ignored if SessionOpts is given) MonitorRetries int // Optional, defaults to 0 which means no retries MonitorRetryTime time.Duration // Optional, defaults to DefaultMonitorRetryTime LockWaitTime time.Duration // Optional, defaults to DefaultLockWaitTime @@ -329,9 +330,12 @@ func (l *Lock) Destroy() error { // createSession is used to create a new managed session func (l *Lock) createSession() (string, error) { session := l.c.Session() - se := &SessionEntry{ - Name: l.opts.SessionName, - TTL: l.opts.SessionTTL, + se := l.opts.SessionOpts + if se == nil { + se = &SessionEntry{ + Name: l.opts.SessionName, + TTL: l.opts.SessionTTL, + } } id, _, err := session.Create(se, nil) if err != nil { diff --git a/vendor/github.com/hashicorp/consul/api/operator.go b/vendor/github.com/hashicorp/consul/api/operator.go new file mode 100644 index 000000000000..a8d04a38eb88 --- /dev/null +++ b/vendor/github.com/hashicorp/consul/api/operator.go @@ -0,0 +1,163 @@ +package api + +// Operator can be used to perform low-level operator tasks for Consul. +type Operator struct { + c *Client +} + +// Operator returns a handle to the operator endpoints. +func (c *Client) Operator() *Operator { + return &Operator{c} +} + +// RaftServer has information about a server in the Raft configuration. +type RaftServer struct { + // ID is the unique ID for the server. These are currently the same + // as the address, but they will be changed to a real GUID in a future + // release of Consul. + ID string + + // Node is the node name of the server, as known by Consul, or this + // will be set to "(unknown)" otherwise. + Node string + + // Address is the IP:port of the server, used for Raft communications. + Address string + + // Leader is true if this server is the current cluster leader. + Leader bool + + // Voter is true if this server has a vote in the cluster. This might + // be false if the server is staging and still coming online, or if + // it's a non-voting server, which will be added in a future release of + // Consul. + Voter bool +} + +// RaftConfigration is returned when querying for the current Raft configuration. +type RaftConfiguration struct { + // Servers has the list of servers in the Raft configuration. + Servers []*RaftServer + + // Index has the Raft index of this configuration. + Index uint64 +} + +// keyringRequest is used for performing Keyring operations +type keyringRequest struct { + Key string +} + +// KeyringResponse is returned when listing the gossip encryption keys +type KeyringResponse struct { + // Whether this response is for a WAN ring + WAN bool + + // The datacenter name this request corresponds to + Datacenter string + + // A map of the encryption keys to the number of nodes they're installed on + Keys map[string]int + + // The total number of nodes in this ring + NumNodes int +} + +// RaftGetConfiguration is used to query the current Raft peer set. +func (op *Operator) RaftGetConfiguration(q *QueryOptions) (*RaftConfiguration, error) { + r := op.c.newRequest("GET", "/v1/operator/raft/configuration") + r.setQueryOptions(q) + _, resp, err := requireOK(op.c.doRequest(r)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var out RaftConfiguration + if err := decodeBody(resp, &out); err != nil { + return nil, err + } + return &out, nil +} + +// RaftRemovePeerByAddress is used to kick a stale peer (one that it in the Raft +// quorum but no longer known to Serf or the catalog) by address in the form of +// "IP:port". +func (op *Operator) RaftRemovePeerByAddress(address string, q *WriteOptions) error { + r := op.c.newRequest("DELETE", "/v1/operator/raft/peer") + r.setWriteOptions(q) + + // TODO (slackpad) Currently we made address a query parameter. Once + // IDs are in place this will be DELETE /v1/operator/raft/peer/. + r.params.Set("address", string(address)) + + _, resp, err := requireOK(op.c.doRequest(r)) + if err != nil { + return err + } + + resp.Body.Close() + return nil +} + +// KeyringInstall is used to install a new gossip encryption key into the cluster +func (op *Operator) KeyringInstall(key string, q *WriteOptions) error { + r := op.c.newRequest("POST", "/v1/operator/keyring") + r.setWriteOptions(q) + r.obj = keyringRequest{ + Key: key, + } + _, resp, err := requireOK(op.c.doRequest(r)) + if err != nil { + return err + } + resp.Body.Close() + return nil +} + +// KeyringList is used to list the gossip keys installed in the cluster +func (op *Operator) KeyringList(q *QueryOptions) ([]*KeyringResponse, error) { + r := op.c.newRequest("GET", "/v1/operator/keyring") + r.setQueryOptions(q) + _, resp, err := requireOK(op.c.doRequest(r)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var out []*KeyringResponse + if err := decodeBody(resp, &out); err != nil { + return nil, err + } + return out, nil +} + +// KeyringRemove is used to remove a gossip encryption key from the cluster +func (op *Operator) KeyringRemove(key string, q *WriteOptions) error { + r := op.c.newRequest("DELETE", "/v1/operator/keyring") + r.setWriteOptions(q) + r.obj = keyringRequest{ + Key: key, + } + _, resp, err := requireOK(op.c.doRequest(r)) + if err != nil { + return err + } + resp.Body.Close() + return nil +} + +// KeyringUse is used to change the active gossip encryption key +func (op *Operator) KeyringUse(key string, q *WriteOptions) error { + r := op.c.newRequest("PUT", "/v1/operator/keyring") + r.setWriteOptions(q) + r.obj = keyringRequest{ + Key: key, + } + _, resp, err := requireOK(op.c.doRequest(r)) + if err != nil { + return err + } + resp.Body.Close() + return nil +} diff --git a/vendor/github.com/hashicorp/consul/api/prepared_query.go b/vendor/github.com/hashicorp/consul/api/prepared_query.go index 63e741e050d5..ff210de3f009 100644 --- a/vendor/github.com/hashicorp/consul/api/prepared_query.go +++ b/vendor/github.com/hashicorp/consul/api/prepared_query.go @@ -43,6 +43,11 @@ type ServiceQuery struct { // this list it must be present. If the tag is preceded with "!" then // it is disallowed. Tags []string + + // NodeMeta is a map of required node metadata fields. If a key/value + // pair is in this map it must be present on the node in order for the + // service entry to be returned. + NodeMeta map[string]string } // QueryTemplate carries the arguments for creating a templated query. @@ -167,19 +172,18 @@ func (c *PreparedQuery) Get(queryID string, q *QueryOptions) ([]*PreparedQueryDe } // Delete is used to delete a specific prepared query. -func (c *PreparedQuery) Delete(queryID string, q *QueryOptions) (*QueryMeta, error) { +func (c *PreparedQuery) Delete(queryID string, q *WriteOptions) (*WriteMeta, error) { r := c.c.newRequest("DELETE", "/v1/query/"+queryID) - r.setQueryOptions(q) + r.setWriteOptions(q) rtt, resp, err := requireOK(c.c.doRequest(r)) if err != nil { return nil, err } defer resp.Body.Close() - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - return qm, nil + wm := &WriteMeta{} + wm.RequestTime = rtt + return wm, nil } // Execute is used to execute a specific prepared query. You can execute using diff --git a/vendor/github.com/hashicorp/consul/api/snapshot.go b/vendor/github.com/hashicorp/consul/api/snapshot.go new file mode 100644 index 000000000000..e902377dd5ca --- /dev/null +++ b/vendor/github.com/hashicorp/consul/api/snapshot.go @@ -0,0 +1,47 @@ +package api + +import ( + "io" +) + +// Snapshot can be used to query the /v1/snapshot endpoint to take snapshots of +// Consul's internal state and restore snapshots for disaster recovery. +type Snapshot struct { + c *Client +} + +// Snapshot returns a handle that exposes the snapshot endpoints. +func (c *Client) Snapshot() *Snapshot { + return &Snapshot{c} +} + +// Save requests a new snapshot and provides an io.ReadCloser with the snapshot +// data to save. If this doesn't return an error, then it's the responsibility +// of the caller to close it. Only a subset of the QueryOptions are supported: +// Datacenter, AllowStale, and Token. +func (s *Snapshot) Save(q *QueryOptions) (io.ReadCloser, *QueryMeta, error) { + r := s.c.newRequest("GET", "/v1/snapshot") + r.setQueryOptions(q) + + rtt, resp, err := requireOK(s.c.doRequest(r)) + if err != nil { + return nil, nil, err + } + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + return resp.Body, qm, nil +} + +// Restore streams in an existing snapshot and attempts to restore it. +func (s *Snapshot) Restore(q *WriteOptions, in io.Reader) error { + r := s.c.newRequest("PUT", "/v1/snapshot") + r.body = in + r.setWriteOptions(q) + _, _, err := requireOK(s.c.doRequest(r)) + if err != nil { + return err + } + return nil +} diff --git a/vendor/vendor.json b/vendor/vendor.json index 6fbd5ef67b10..b3587ece60af 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -1634,11 +1634,11 @@ "revisionTime": "2016-11-07T20:49:10Z" }, { - "checksumSHA1": "ZY6NCrR80zUmtOtPtKffbmFxRWw=", + "checksumSHA1": "ygEjA1d52B1RDmZu8+1WTwkrYDQ=", "comment": "v0.6.3-28-g3215b87", "path": "github.com/hashicorp/consul/api", - "revision": "6e061b2d580d80347b7c5c4dfc8730de7403a145", - "revisionTime": "2016-07-03T02:45:54Z" + "revision": "48d7b069ad443a48ffa93364048ff8909b5d1fa2", + "revisionTime": "2017-02-07T15:38:46Z" }, { "checksumSHA1": "cdOCt0Yb+hdErz8NAQqayxPmRsY=", From 15fb969f3e8bd52c1312ee8ce7d311d03bc9df08 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Thu, 9 Feb 2017 02:10:30 -0800 Subject: [PATCH 04/23] Add an attribute reader interface and a config reader implementation. --- builtin/providers/consul/attr_reader.go | 17 +++ .../providers/consul/attr_reader_config.go | 111 ++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 builtin/providers/consul/attr_reader.go create mode 100644 builtin/providers/consul/attr_reader_config.go diff --git a/builtin/providers/consul/attr_reader.go b/builtin/providers/consul/attr_reader.go new file mode 100644 index 000000000000..1e9ca769760d --- /dev/null +++ b/builtin/providers/consul/attr_reader.go @@ -0,0 +1,17 @@ +package consul + +import "time" + +type _AttrReader interface { + GetBool(_SchemaAttr) bool + GetBoolOK(_SchemaAttr) (b, ok bool) + GetDurationOK(_SchemaAttr) (time.Duration, bool) + GetFloat64OK(_SchemaAttr) (float64, bool) + GetIntOK(_SchemaAttr) (int, bool) + GetIntPtr(_SchemaAttr) *int + GetString(_SchemaAttr) string + GetStringOK(_SchemaAttr) (string, bool) + GetStringPtr(_SchemaAttr) *string + GetStringSlice(attrName _SchemaAttr) []string + BackingType() string +} diff --git a/builtin/providers/consul/attr_reader_config.go b/builtin/providers/consul/attr_reader_config.go new file mode 100644 index 000000000000..56d88ed50cdf --- /dev/null +++ b/builtin/providers/consul/attr_reader_config.go @@ -0,0 +1,111 @@ +package consul + +import ( + "time" + + "github.com/hashicorp/terraform/helper/schema" +) + +type _ConfigReader struct { + d *schema.ResourceData +} + +func _NewConfigReader(d *schema.ResourceData) *_ConfigReader { + return &_ConfigReader{ + d: d, + } +} + +func (r *_ConfigReader) BackingType() string { + return "config" +} + +func (r *_ConfigReader) GetBool(attrName _SchemaAttr) bool { + if v, ok := r.d.GetOk(string(attrName)); ok { + return v.(bool) + } + + return false +} + +func (r *_ConfigReader) GetBoolOK(attrName _SchemaAttr) (b, ok bool) { + if v, ok := r.d.GetOk(string(attrName)); ok { + return v.(bool), true + } + + return false, false +} + +func (r *_ConfigReader) GetDurationOK(attrName _SchemaAttr) (time.Duration, bool) { + if v, ok := r.d.GetOk(string(attrName)); ok { + d, err := time.ParseDuration(v.(string)) + if err != nil { + return time.Duration(0), false + } + return d, true + } + + return time.Duration(0), false +} + +func (r *_ConfigReader) GetFloat64OK(attrName _SchemaAttr) (float64, bool) { + if v, ok := r.d.GetOk(string(attrName)); ok { + return v.(float64), true + } + + return 0.0, false +} + +func (r *_ConfigReader) GetIntOK(attrName _SchemaAttr) (int, bool) { + if v, ok := r.d.GetOk(string(attrName)); ok { + return v.(int), true + } + + return 0, false +} + +func (r *_ConfigReader) GetIntPtr(attrName _SchemaAttr) *int { + if v, ok := r.d.GetOk(string(attrName)); ok { + i := v.(int) + return &i + } + + return nil +} + +func (r *_ConfigReader) GetString(attrName _SchemaAttr) string { + if v, ok := r.d.GetOk(string(attrName)); ok { + return v.(string) + } + + return "" +} + +func (r *_ConfigReader) GetStringOK(attrName _SchemaAttr) (string, bool) { + if v, ok := r.d.GetOk(string(attrName)); ok { + return v.(string), true + } + + return "", false +} + +func (r *_ConfigReader) GetStringPtr(attrName _SchemaAttr) *string { + if v, ok := r.d.GetOk(string(attrName)); ok { + switch v.(type) { + case string: + s := v.(string) + return &s + case *string: + return v.(*string) + } + } + + return nil +} + +func (r *_ConfigReader) GetStringSlice(attrName _SchemaAttr) []string { + if listRaw, ok := r.d.GetOk(string(attrName)); ok { + return listRaw.([]string) + } + return nil +} From db2f217f25cf4a18b2a3e22870277bab40f90e42 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Thu, 9 Feb 2017 02:11:59 -0800 Subject: [PATCH 05/23] Change the signature of map writer to take a map that isn't a pointer. Force the use of `ToMap()` to retrieve the created `map[string]interface{}`. --- builtin/providers/consul/attr_writer_map.go | 16 +++++++++++----- builtin/providers/consul/utils.go | 5 ++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/builtin/providers/consul/attr_writer_map.go b/builtin/providers/consul/attr_writer_map.go index 82bab523483a..1a46e54bc105 100644 --- a/builtin/providers/consul/attr_writer_map.go +++ b/builtin/providers/consul/attr_writer_map.go @@ -8,10 +8,10 @@ import ( ) type _AttrWriterMap struct { - m *map[string]interface{} + m map[string]interface{} } -func _NewMapWriter(m *map[string]interface{}) *_AttrWriterMap { +func _NewMapWriter(m map[string]interface{}) *_AttrWriterMap { return &_AttrWriterMap{ m: m, } @@ -37,12 +37,12 @@ func (w *_AttrWriterMap) Set(name _SchemaAttr, v interface{}) error { } func (w *_AttrWriterMap) SetBool(name _SchemaAttr, b bool) error { - (*w.m)[string(name)] = fmt.Sprintf("%t", b) + w.m[string(name)] = fmt.Sprintf("%t", b) return nil } func (w *_AttrWriterMap) SetFloat64(name _SchemaAttr, f float64) error { - (*w.m)[string(name)] = strconv.FormatFloat(f, 'g', -1, 64) + w.m[string(name)] = strconv.FormatFloat(f, 'g', -1, 64) return nil } @@ -51,6 +51,8 @@ func (w *_AttrWriterMap) SetList(name _SchemaAttr, l []interface{}) error { } func (w *_AttrWriterMap) SetMap(name _SchemaAttr, m map[string]interface{}) error { + w.m[string(name)] = m + return nil panic(fmt.Sprintf("PROVIDER BUG: Cat set a map within a map for %s", name)) } @@ -59,6 +61,10 @@ func (w *_AttrWriterMap) SetSet(name _SchemaAttr, s *schema.Set) error { } func (w *_AttrWriterMap) SetString(name _SchemaAttr, s string) error { - (*w.m)[string(name)] = s + w.m[string(name)] = s return nil } + +func (w *_AttrWriterMap) ToMap() map[string]interface{} { + return w.m +} diff --git a/builtin/providers/consul/utils.go b/builtin/providers/consul/utils.go index d3594a50ef17..4cb9533df583 100644 --- a/builtin/providers/consul/utils.go +++ b/builtin/providers/consul/utils.go @@ -242,8 +242,7 @@ func _APIToStateMap(e *_TypeEntry, v interface{}, w _AttrWriter) error { return fmt.Errorf("PROVIDER BUG: unable to cast %s to a map", e.SchemaName) } - m := make(map[string]interface{}, len(rawMap)) - mWriter := _NewMapWriter(&m) + mWriter := _NewMapWriter(make(map[string]interface{}, len(rawMap))) // Make a lookup map by API Schema Name var setMembersLen int @@ -271,7 +270,7 @@ func _APIToStateMap(e *_TypeEntry, v interface{}, w _AttrWriter) error { } } - return w.SetMap(e.SchemaName, m) + return w.SetMap(e.SchemaName, mWriter.ToMap()) } func _APIToStateSet(e *_TypeEntry, v interface{}, w _AttrWriter) error { From ac1294633aa803d8b7ee2f48f2bb1eec9062943c Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Thu, 9 Feb 2017 09:01:38 -0800 Subject: [PATCH 06/23] Add a datasource for catalog nodes. --- .../data_source_consul_catalog_nodes.go | 388 ++++++++++++++++++ .../data_source_consul_catalog_nodes_test.go | 36 ++ builtin/providers/consul/resource_provider.go | 5 +- builtin/providers/consul/utils.go | 237 ++++++++--- 4 files changed, 609 insertions(+), 57 deletions(-) create mode 100644 builtin/providers/consul/data_source_consul_catalog_nodes.go create mode 100644 builtin/providers/consul/data_source_consul_catalog_nodes_test.go diff --git a/builtin/providers/consul/data_source_consul_catalog_nodes.go b/builtin/providers/consul/data_source_consul_catalog_nodes.go new file mode 100644 index 000000000000..8bb707c2d669 --- /dev/null +++ b/builtin/providers/consul/data_source_consul_catalog_nodes.go @@ -0,0 +1,388 @@ +package consul + +import ( + "fmt" + "time" + + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform/helper/schema" +) + +// Top-level consul_catalog_nodes attributes +const ( + _CatalogNodes _TypeKey = iota + _CatalogNodesAllowStale + _CatalogNodesDatacenter + _CatalogNodesNear + _CatalogNodesRequireConsistent + _CatalogNodesToken + _CatalogNodesWaitIndex + _CatalogNodesWaitTime +) + +// node.* attributes +const ( + _CatalogNodeID _TypeKey = iota + _CatalogNodeName + _CatalogNodeAddress + _CatalogNodeTaggedAddresses + _CatalogNodeMeta +) + +// node.tagged_addresses.* attributes +const ( + _CatalogNodeTaggedAddressesLAN _TypeKey = iota + _CatalogNodeTaggedAddressesWAN +) + +var _CatalogNodeAttrs = map[_TypeKey]*_TypeEntry{ + _CatalogNodeID: { + APIName: "ID", + SchemaName: "id", + Source: _SourceAPIResult, + Type: schema.TypeString, + ValidateFuncs: []interface{}{ + _ValidateRegexp(`^[\S]+$`), + }, + APITest: func(e *_TypeEntry, v interface{}) (interface{}, bool) { + node := v.(*consulapi.Node) + + if id := node.ID; id != "" { + return id, true + } + + // Use the node name - confusingly stored in the Node attribute - if no ID + // is available. + if name := node.Node; name != "" { + return name, true + } + + return "", false + }, + }, + _CatalogNodeName: { + APIName: "Name", + SchemaName: "name", + Source: _SourceAPIResult, + Type: schema.TypeString, + ValidateFuncs: []interface{}{ + _ValidateRegexp(`^[\S]+$`), + }, + APITest: func(e *_TypeEntry, v interface{}) (interface{}, bool) { + node := v.(*consulapi.Node) + + if name := node.Node; name != "" { + return name, true + } + + return "", false + }, + }, + _CatalogNodeAddress: { + APIName: "Address", + SchemaName: "address", + Source: _SourceAPIResult, + Type: schema.TypeString, + APITest: func(e *_TypeEntry, v interface{}) (interface{}, bool) { + node := v.(*consulapi.Node) + + if addr := node.Address; addr != "" { + return addr, true + } + + return "", false + }, + }, + _CatalogNodeTaggedAddresses: { + APIName: "TaggedAddresses", + SchemaName: "tagged_addresses", + Source: _SourceAPIResult, + Type: schema.TypeMap, + SetMembers: map[_TypeKey]*_TypeEntry{ + _CatalogNodeTaggedAddressesLAN: { + APIName: "LAN", + SchemaName: "lan", + Source: _SourceAPIResult, + Type: schema.TypeString, + APITest: func(e *_TypeEntry, v interface{}) (interface{}, bool) { + m := v.(map[string]string) + + if addr, found := m[string(e.SchemaName)]; found { + return addr, true + } + + return nil, false + }, + }, + _CatalogNodeTaggedAddressesWAN: { + APIName: "WAN", + SchemaName: "wan", + Source: _SourceAPIResult, + Type: schema.TypeString, + APITest: func(e *_TypeEntry, v interface{}) (interface{}, bool) { + m := v.(map[string]string) + + if addr, found := m[string(e.SchemaName)]; found { + return addr, true + } + + return nil, false + }, + }, + }, + APITest: func(e *_TypeEntry, v interface{}) (interface{}, bool) { + node := v.(*consulapi.Node) + + if addrs := node.TaggedAddresses; len(addrs) > 0 { + return _MapStringToMapInterface(addrs), true + } + + return nil, false + }, + }, + _CatalogNodeMeta: { + APIName: "Meta", + SchemaName: "meta", + Source: _SourceAPIResult, + Type: schema.TypeMap, + APITest: func(e *_TypeEntry, v interface{}) (interface{}, bool) { + node := v.(*consulapi.Node) + + if meta := node.Meta; len(meta) > 0 { + return _MapStringToMapInterface(meta), true + } + + return nil, false + }, + }, +} + +var _CatalogNodesAttrs = map[_TypeKey]*_TypeEntry{ + _CatalogNodesAllowStale: { + SchemaName: "allow_stale", + Source: _SourceLocalFilter, + Type: schema.TypeBool, + Default: true, + ConfigRead: func(e *_TypeEntry, r _AttrReader) (interface{}, bool) { + b, ok := r.GetBoolOK(e.SchemaName) + if !ok { + return nil, false + } + + return b, true + }, + ConfigUse: func(e *_TypeEntry, v interface{}, target interface{}) error { + b := v.(bool) + queryOpts := target.(*consulapi.QueryOptions) + queryOpts.AllowStale = b + return nil + }, + }, + _CatalogNodesDatacenter: { + SchemaName: "datacenter", + Source: _SourceLocalFilter, + Type: schema.TypeString, + ConfigRead: func(e *_TypeEntry, r _AttrReader) (interface{}, bool) { + s, ok := r.GetStringOK(e.SchemaName) + if !ok { + return nil, false + } + + return s, true + }, + ConfigUse: func(e *_TypeEntry, v interface{}, target interface{}) error { + s := v.(string) + queryOpts := target.(*consulapi.QueryOptions) + queryOpts.Datacenter = s + return nil + }, + }, + _CatalogNodesNear: { + SchemaName: "near", + Source: _SourceLocalFilter, + Type: schema.TypeString, + ConfigRead: func(e *_TypeEntry, r _AttrReader) (interface{}, bool) { + s, ok := r.GetStringOK(e.SchemaName) + if !ok { + return nil, false + } + + return s, true + }, + ConfigUse: func(e *_TypeEntry, v interface{}, target interface{}) error { + s := v.(string) + queryOpts := target.(*consulapi.QueryOptions) + queryOpts.Near = s + return nil + }, + }, + _CatalogNodes: { + SchemaName: "nodes", + Source: _SourceAPIResult, + Type: schema.TypeList, + ListSchema: _CatalogNodeAttrs, + }, + _CatalogNodesRequireConsistent: { + SchemaName: "require_consistent", + Source: _SourceLocalFilter, + Type: schema.TypeBool, + Default: false, + ConfigRead: func(e *_TypeEntry, r _AttrReader) (interface{}, bool) { + b, ok := r.GetBoolOK(e.SchemaName) + if !ok { + return nil, false + } + + return b, true + }, + ConfigUse: func(e *_TypeEntry, v interface{}, target interface{}) error { + b := v.(bool) + queryOpts := target.(*consulapi.QueryOptions) + queryOpts.RequireConsistent = b + return nil + }, + }, + _CatalogNodesToken: { + SchemaName: "token", + Source: _SourceLocalFilter, + Type: schema.TypeString, + ConfigRead: func(e *_TypeEntry, r _AttrReader) (interface{}, bool) { + s, ok := r.GetStringOK(e.SchemaName) + if !ok { + return nil, false + } + + return s, true + }, + ConfigUse: func(e *_TypeEntry, v interface{}, target interface{}) error { + s := v.(string) + queryOpts := target.(*consulapi.QueryOptions) + queryOpts.Token = s + return nil + }, + }, + _CatalogNodesWaitIndex: { + SchemaName: "wait_index", + Source: _SourceLocalFilter, + Type: schema.TypeInt, + ValidateFuncs: []interface{}{ + _ValidateIntMin(0), + }, + ConfigRead: func(e *_TypeEntry, r _AttrReader) (interface{}, bool) { + i, ok := r.GetIntOK(e.SchemaName) + if !ok { + return nil, false + } + + return uint64(i), true + }, + ConfigUse: func(e *_TypeEntry, v interface{}, target interface{}) error { + i := v.(uint64) + queryOpts := target.(*consulapi.QueryOptions) + queryOpts.WaitIndex = i + return nil + }, + }, + _CatalogNodesWaitTime: { + SchemaName: "wait_time", + Source: _SourceLocalFilter, + Type: schema.TypeString, + ValidateFuncs: []interface{}{ + _ValidateDurationMin("0ns"), + }, + ConfigRead: func(e *_TypeEntry, r _AttrReader) (interface{}, bool) { + d, ok := r.GetDurationOK(e.SchemaName) + if !ok { + return nil, false + } + + return d, true + }, + ConfigUse: func(e *_TypeEntry, v interface{}, target interface{}) error { + d := v.(time.Duration) + queryOpts := target.(*consulapi.QueryOptions) + queryOpts.WaitTime = d + return nil + }, + }, +} + +func dataSourceConsulCatalogNodes() *schema.Resource { + return &schema.Resource{ + Read: dataSourceConsulCatalogNodesRead, + Schema: _TypeEntryMapToSchema(_CatalogNodesAttrs), + } +} + +func dataSourceConsulCatalogNodesRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*consulapi.Client) + + dc, err := getDC(d, client) + if err != nil { + return err + } + + queryOpts := &consulapi.QueryOptions{ + Datacenter: dc, + } + + cfgReader := _NewConfigReader(d) + + // Construct the query options + for _, e := range _CatalogNodesAttrs[_CatalogNodes].ListSchema { + // Only evaluate attributes that impact the state + if e.Source&_SourceLocalFilter == 0 { + continue + } + + if v, ok := e.ConfigRead(e, cfgReader); ok { + if err := e.ConfigUse(e, v, queryOpts); err != nil { + return errwrap.Wrapf(fmt.Sprintf("error writing %q's query option: {{err}}", e.SchemaName), err) + } + } + } + + nodes, meta, err := client.Catalog().Nodes(queryOpts) + if err != nil { + return err + } + + // TODO(sean@): It'd be nice if this data source had a way of filtering out + // irrelevant data so only the important bits are persisted in the state file. + // Something like an attribute mask or even a regexp of matching schema + // attributesknames would be sufficient in the most basic case. Food for + // thought. + + l := make([]interface{}, 0, len(nodes)) + + for _, node := range nodes { + mWriter := _NewMapWriter(make(map[string]interface{}, len(_CatalogNodeAttrs))) + + // /v1/catalog/nodes returns a list of node objects + for _, e := range _CatalogNodesAttrs[_CatalogNodes].ListSchema { + // Only evaluate attributes that impact the state + if e.Source&_ModifyState == 0 { + continue + } + + h := e.MustLookupTypeHandler() + + if v, ok := h.APITest(e, node); ok { + if err := h.APIToState(e, v, mWriter); err != nil { + return errwrap.Wrapf(fmt.Sprintf("error writing %q's data to state: {{err}}", e.SchemaName), err) + } + } + } + + l = append(l, mWriter.ToMap()) + } + + dataSourceWriter := _NewStateWriter(d) + dataSourceWriter.SetList(_CatalogNodesAttrs[_CatalogNodes].SchemaName, l) + dataSourceWriter.SetString(_CatalogNodesAttrs[_CatalogNodesDatacenter].SchemaName, dc) + const idKeyFmt = "catalog-nodes-%s" + dataSourceWriter.SetID(fmt.Sprintf(idKeyFmt, dc)) + + return nil +} diff --git a/builtin/providers/consul/data_source_consul_catalog_nodes_test.go b/builtin/providers/consul/data_source_consul_catalog_nodes_test.go new file mode 100644 index 000000000000..ede6f4342891 --- /dev/null +++ b/builtin/providers/consul/data_source_consul_catalog_nodes_test.go @@ -0,0 +1,36 @@ +package consul + +import ( + "testing" + + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccDataConsulCatalogNodes_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccDataConsulCatalogNodesConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckDataSourceValue("data.consul_catalog_nodes.read", "nodes.#", "1"), + testAccCheckDataSourceValue("data.consul_catalog_nodes.read", "nodes.0.id", ""), + testAccCheckDataSourceValue("data.consul_catalog_nodes.read", "nodes.0.name", ""), + testAccCheckDataSourceValue("data.consul_catalog_nodes.read", "nodes.0.address", ""), + ), + }, + }, + }) +} + +const testAccDataConsulCatalogNodesConfig = ` +data "consul_catalog_nodes" "read" { + allow_stale = true + require_consistent = false + near = "_agent" + token = "" + wait_index = 0 + wait_time = "1m" +} +` diff --git a/builtin/providers/consul/resource_provider.go b/builtin/providers/consul/resource_provider.go index 4688f543cde6..749223c5d6b0 100644 --- a/builtin/providers/consul/resource_provider.go +++ b/builtin/providers/consul/resource_provider.go @@ -64,8 +64,9 @@ func Provider() terraform.ResourceProvider { }, DataSourcesMap: map[string]*schema.Resource{ - "consul_agent_self": dataSourceConsulAgentSelf(), - "consul_keys": dataSourceConsulKeys(), + "consul_agent_self": dataSourceConsulAgentSelf(), + "consul_catalog_nodes": dataSourceConsulCatalogNodes(), + "consul_keys": dataSourceConsulKeys(), }, ResourcesMap: map[string]*schema.Resource{ diff --git a/builtin/providers/consul/utils.go b/builtin/providers/consul/utils.go index 4cb9533df583..a23429b2b18c 100644 --- a/builtin/providers/consul/utils.go +++ b/builtin/providers/consul/utils.go @@ -6,6 +6,7 @@ import ( "regexp" "sort" "strconv" + "time" "github.com/hashicorp/errwrap" "github.com/hashicorp/terraform/helper/hashcode" @@ -31,6 +32,12 @@ type _TypeKey int // function objects that are dynamically constructed and executed. type _ValidatorInputs []interface{} +// _ValidateDurationMin is the minimum duration to accept as input +type _ValidateDurationMin string + +// _ValidateIntMin is the minimum integer value to accept as input +type _ValidateIntMin int + // _ValidateRegexp is a regexp pattern to use to validate schema input. type _ValidateRegexp string @@ -46,29 +53,61 @@ const ( // _SourceAPIResult indicates the parameter may only be set by the return of // an API call. _SourceAPIResult + + // _SourceLocalFilter indicates the parameter is only used as input to the + // resource or data source and not to be entered into the state file. + _SourceLocalFilter +) + +const ( + // _ModifyState is a mask that selects all attribute sources that can modify + // the state (i.e. everything but filters used in data sources). + _ModifyState = _SourceUserRequired | _SourceUserOptional | _SourceAPIResult + + // _ComputedAttrMask is a mask that selects _Source*'s that are Computed in the + // schema. + _ComputedAttrMask = _SourceAPIResult + + // _OptionalAttrMask is a mask that selects _Source*'s that are Optional in the + // schema. + _OptionalAttrMask = _SourceAPIResult | _SourceLocalFilter + + // _RequiredAttrMask is a mask that selects _Source*'s that are Required in the + // schema. + _RequiredAttrMask = _SourceUserRequired ) type _TypeEntry struct { APIName _APIAttr APIAliases []_APIAttr Source _SourceFlags + Default interface{} Description string SchemaName _SchemaAttr Type schema.ValueType ValidateFuncs []interface{} SetMembers map[_TypeKey]*_TypeEntry + ListSchema map[_TypeKey]*_TypeEntry // APITest, if returns true, will call APIToState. The if the value was // found, the second return parameter will include the value that should be // set in the state store. - APITest func(*_TypeEntry, map[string]interface{}) (interface{}, bool) + APITest func(*_TypeEntry, interface{}) (interface{}, bool) // APIToState takes the value from APITest and writes it to the _AttrWriter APIToState func(*_TypeEntry, interface{}, _AttrWriter) error + + // ConfigRead, if it returns true, returned a value that will be passed to its + // ConfigUse handler. + ConfigRead func(*_TypeEntry, _AttrReader) (interface{}, bool) + + // ConfigUse takes the value returned from ConfigRead as the second argument + // and a 3rd optional opaque context argument. + ConfigUse func(e *_TypeEntry, v interface{}, target interface{}) error } type _TypeHandlers struct { - APITest func(*_TypeEntry, map[string]interface{}) (interface{}, bool) + APITest func(*_TypeEntry, interface{}) (interface{}, bool) APIToState func(*_TypeEntry, interface{}, _AttrWriter) error } @@ -99,8 +138,10 @@ var _TypeHandlerLookupMap = map[schema.ValueType]*_TypeHandlers{ }, } -func _APITestBool(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) { - v, found := self[string(e.APIName)] +func _APITestBool(e *_TypeEntry, self interface{}) (interface{}, bool) { + m := self.(map[string]interface{}) + + v, found := m[string(e.APIName)] if found { if b, ok := v.(bool); ok { return b, true @@ -112,8 +153,10 @@ func _APITestBool(e *_TypeEntry, self map[string]interface{}) (interface{}, bool return false, false } -func _APITestFloat64(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) { - v, found := self[string(e.APIName)] +func _APITestFloat64(e *_TypeEntry, self interface{}) (interface{}, bool) { + m := self.(map[string]interface{}) + + v, found := m[string(e.APIName)] if found { if f, ok := v.(float64); ok { return f, true @@ -124,22 +167,26 @@ func _APITestFloat64(e *_TypeEntry, self map[string]interface{}) (interface{}, b return 0.0, false } -func _APITestID(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) { - v, _ := _APITestString(e, self) +func _APITestID(e *_TypeEntry, self interface{}) (interface{}, bool) { + m := self.(map[string]interface{}) + + v, _ := _APITestString(e, m) // Unconditionally return true so that the call to the APIToState handler can // return an error. return v, true } -func _APITestList(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) { +func _APITestList(e *_TypeEntry, self interface{}) (interface{}, bool) { + m := self.(map[string]interface{}) + names := append([]_APIAttr{e.APIName}, e.APIAliases...) const defaultListLen = 8 l := make([]interface{}, 0, defaultListLen) var foundName bool for _, name := range names { - v, found := self[string(name)] + v, found := m[string(name)] if found { foundName = true // TODO(sean@): should make a list writer that normalizes v.(type) to a @@ -162,7 +209,9 @@ func _APITestList(e *_TypeEntry, self map[string]interface{}) (interface{}, bool return []interface{}{}, false } -func _APITestMap(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) { +func _APITestMap(e *_TypeEntry, selfRaw interface{}) (interface{}, bool) { + self := selfRaw.(map[string]interface{}) + v, found := self[string(e.APIName)] if found { if m, ok := v.(map[string]interface{}); ok { @@ -174,7 +223,9 @@ func _APITestMap(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) return "", false } -func _APITestSet(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) { +func _APITestSet(e *_TypeEntry, selfRaw interface{}) (interface{}, bool) { + self := selfRaw.(map[string]interface{}) + v, found := self[string(e.APIName)] if found { if m, ok := v.(map[string]interface{}); ok { @@ -186,7 +237,9 @@ func _APITestSet(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) return "", false } -func _APITestString(e *_TypeEntry, self map[string]interface{}) (interface{}, bool) { +func _APITestString(e *_TypeEntry, selfRaw interface{}) (interface{}, bool) { + self := selfRaw.(map[string]interface{}) + v, found := self[string(e.APIName)] if found { if s, ok := v.(string); ok { @@ -361,6 +414,33 @@ func (e *_TypeEntry) LookupDefaultTypeHandler() *_TypeHandlers { return h } +func (e *_TypeEntry) MustLookupTypeHandler() *_TypeHandlers { + h := &_TypeHandlers{ + APITest: e.APITest, + APIToState: e.APIToState, + } + + defaultHandler := e.LookupDefaultTypeHandler() + + if h.APITest == nil { + h.APITest = defaultHandler.APITest + + if h.APITest == nil { + panic(fmt.Sprint("PROVIDER BUG: %v missing APITest method", e.SchemaName)) + } + } + + if h.APIToState == nil { + h.APIToState = defaultHandler.APIToState + + if h.APIToState == nil { + panic(fmt.Sprint("PROVIDER BUG: %v missing APIToState method", e.SchemaName)) + } + } + + return h +} + // _NegateBoolToState is a factory function that creates a new function that // negates whatever the bool is that's passed in as an argument. func _NegateBoolToState(fn func(*_TypeEntry, interface{}, _AttrWriter) error) func(*_TypeEntry, interface{}, _AttrWriter) error { @@ -384,43 +464,42 @@ func _StateSet(d *schema.ResourceData, attrName _SchemaAttr, v interface{}) erro return nil } +func _TypeEntryListToSchema(e *_TypeEntry) map[string]*schema.Schema { + return map[string]*schema.Schema{ + string(e.SchemaName): e.ToSchema(), + } +} + +func _TypeEntryMapToResource(in map[_TypeKey]*_TypeEntry) *schema.Resource { + return &schema.Resource{ + Schema: _TypeEntryMapToSchema(in), + } +} + func _TypeEntryMapToSchema(in map[_TypeKey]*_TypeEntry) map[string]*schema.Schema { out := make(map[string]*schema.Schema, len(in)) for _, e := range in { - e.Validate() - - attr := &schema.Schema{ - Type: e.Type, - Description: e.Description, - Optional: e.Source&_SourceAPIResult == _SourceAPIResult, - Required: e.Source&_SourceUserRequired == _SourceUserRequired, - Computed: e.Source&_SourceAPIResult == _SourceAPIResult, - ValidateFunc: e.MakeValidationFunc(), - } - - // Fixup the type: use the real type vs a surrogate type - switch e.Type { - case schema.TypeList: - attr.Elem = &schema.Schema{ - Type: schema.TypeString, - } - case schema.TypeSet: - attr.Elem = &schema.Resource{ - Schema: _TypeEntryMapToSchema(e.SetMembers), - } - } - - out[string(e.SchemaName)] = attr + out[string(e.SchemaName)] = e.ToSchema() } return out } func (e *_TypeEntry) Validate() { - if e.Source&_SourceAPIResult == _SourceAPIResult && e.Type == schema.TypeSet { + if e.Source&_SourceAPIResult != 0 && e.Type == schema.TypeSet { panic(fmt.Sprintf("PROVIDER BUG: %s can not be computed and of type Set", e.SchemaName)) } + if e.Source&_SourceLocalFilter != 0 { + if e.ConfigRead == nil { + panic(fmt.Sprintf("PROVIDER BUG: %s can not be configured as a local filter and be missing a config read handler", e.SchemaName)) + } + + if e.ConfigUse == nil { + panic(fmt.Sprintf("PROVIDER BUG: %s can not be configured as a local filter and be missing a config use handler", e.SchemaName)) + } + } + if len(e.SetMembers) != 0 && !(e.Type == schema.TypeSet || e.Type == schema.TypeMap) { panic(fmt.Sprintf("PROVIDER BUG: %s is not of type Set but has SetMembers set", e.SchemaName)) } @@ -438,9 +517,13 @@ func (e *_TypeEntry) MakeValidationFunc() func(v interface{}, key string) (warni return nil } - fns := make([]func(v interface{}, key string) (warnings []string, errors []error), len(e.ValidateFuncs)) + fns := make([]func(v interface{}, key string) (warnings []string, errors []error), 0, len(e.ValidateFuncs)) for _, v := range e.ValidateFuncs { switch u := v.(type) { + case _ValidateDurationMin: + fns = append(fns, _ValidateDurationMinFactory(e, string(u))) + case _ValidateIntMin: + fns = append(fns, _ValidateIntMinFactory(e, int(u))) case _ValidateRegexp: fns = append(fns, _ValidateRegexpFactory(e, string(u))) } @@ -457,29 +540,73 @@ func (e *_TypeEntry) MakeValidationFunc() func(v interface{}, key string) (warni } } -// _ValidateFuncs takes a list of typed validator inputs, creates validation -// functions for each and then runs them in serial until either a warning or -// error is returned from the first validation function. -func _ValidateFuncs(e *_TypeEntry, in ...interface{}) func(v interface{}, key string) (warnings []string, errors []error) { - if len(in) == 0 { - return nil +func (e *_TypeEntry) ToSchema() *schema.Schema { + e.Validate() + + attr := &schema.Schema{ + Computed: e.Source&_ComputedAttrMask != 0, + Default: e.Default, + Description: e.Description, + Optional: e.Source&_OptionalAttrMask != 0, + Required: e.Source&_RequiredAttrMask != 0, + Type: e.Type, + ValidateFunc: e.MakeValidationFunc(), } - fns := make([]func(v interface{}, key string) (warnings []string, errors []error), len(in)) - for _, v := range in { - switch v.(type) { - case _ValidateRegexp: - fns = append(fns, _ValidateRegexpFactory(e, v.(string))) + // Fixup the type: use the real type vs a surrogate type + switch e.Type { + case schema.TypeList: + if e.ListSchema == nil { + attr.Elem = &schema.Schema{ + Type: schema.TypeString, + } + } else { + attr.Elem = _TypeEntryMapToResource(e.ListSchema) + } + + case schema.TypeSet: + attr.Elem = &schema.Resource{ + Schema: _TypeEntryMapToSchema(e.SetMembers), + } + } + + return attr +} + +func _MapStringToMapInterface(in map[string]string) map[string]interface{} { + out := make(map[string]interface{}, len(in)) + for k, v := range in { + out[k] = v + } + return out +} + +func _ValidateDurationMinFactory(e *_TypeEntry, minDuration string) func(v interface{}, key string) (warnings []string, errors []error) { + dMin, err := time.ParseDuration(minDuration) + if err != nil { + panic(fmt.Sprintf("PROVIDER BUG: duration %q not valid: %#v", minDuration, err)) + } + + return func(v interface{}, key string) (warnings []string, errors []error) { + d, err := time.ParseDuration(v.(string)) + if err != nil { + errors = append(errors, errwrap.Wrapf(fmt.Sprintf("Invalid %s specified (%q): {{err}}", e.SchemaName), err)) } + + if d < dMin { + errors = append(errors, fmt.Errorf("Invalid %s specified: duration %q less than the required minimum %s", e.SchemaName, v.(string), dMin)) + } + + return warnings, errors } +} +func _ValidateIntMinFactory(e *_TypeEntry, min int) func(v interface{}, key string) (warnings []string, errors []error) { return func(v interface{}, key string) (warnings []string, errors []error) { - for _, fn := range fns { - warnings, errors = fn(v, key) - if len(warnings) > 0 || len(errors) > 0 { - break - } + if v.(int) < min { + errors = append(errors, fmt.Errorf("Invalid %s specified: %d less than the required minimum %d", e.SchemaName, v.(int), min)) } + return warnings, errors } } From 0d5ee1e953058bc41f2a6ab7185125c0f1182e79 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Thu, 9 Feb 2017 09:02:15 -0800 Subject: [PATCH 07/23] Catch API drift with Consul. --- builtin/providers/consul/resource_consul_prepared_query.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builtin/providers/consul/resource_consul_prepared_query.go b/builtin/providers/consul/resource_consul_prepared_query.go index 329bd2f7d896..28ff2bf8251c 100644 --- a/builtin/providers/consul/resource_consul_prepared_query.go +++ b/builtin/providers/consul/resource_consul_prepared_query.go @@ -208,12 +208,12 @@ func resourceConsulPreparedQueryRead(d *schema.ResourceData, meta interface{}) e func resourceConsulPreparedQueryDelete(d *schema.ResourceData, meta interface{}) error { client := meta.(*consulapi.Client) - qo := &consulapi.QueryOptions{ + writeOpts := &consulapi.WriteOptions{ Datacenter: d.Get("datacenter").(string), Token: d.Get("token").(string), } - if _, err := client.PreparedQuery().Delete(d.Id(), qo); err != nil { + if _, err := client.PreparedQuery().Delete(d.Id(), writeOpts); err != nil { return err } From 556773281445e168489f419c421c1a8ad876c426 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Thu, 9 Feb 2017 17:23:37 -0800 Subject: [PATCH 08/23] Remove underscores from private identifiers that were not to be exported and strictly use lowercase letters instead. --- builtin/providers/consul/attr_reader.go | 22 +- .../providers/consul/attr_reader_config.go | 28 +- builtin/providers/consul/attr_writer.go | 14 +- builtin/providers/consul/attr_writer_map.go | 24 +- builtin/providers/consul/attr_writer_state.go | 34 +- .../consul/data_source_consul_agent_self.go | 690 +++++++++--------- .../data_source_consul_catalog_nodes.go | 172 ++--- builtin/providers/consul/utils.go | 252 +++---- 8 files changed, 618 insertions(+), 618 deletions(-) diff --git a/builtin/providers/consul/attr_reader.go b/builtin/providers/consul/attr_reader.go index 1e9ca769760d..fa79a69beb2f 100644 --- a/builtin/providers/consul/attr_reader.go +++ b/builtin/providers/consul/attr_reader.go @@ -2,16 +2,16 @@ package consul import "time" -type _AttrReader interface { - GetBool(_SchemaAttr) bool - GetBoolOK(_SchemaAttr) (b, ok bool) - GetDurationOK(_SchemaAttr) (time.Duration, bool) - GetFloat64OK(_SchemaAttr) (float64, bool) - GetIntOK(_SchemaAttr) (int, bool) - GetIntPtr(_SchemaAttr) *int - GetString(_SchemaAttr) string - GetStringOK(_SchemaAttr) (string, bool) - GetStringPtr(_SchemaAttr) *string - GetStringSlice(attrName _SchemaAttr) []string +type attrReader interface { + GetBool(schemaAttr) bool + GetBoolOK(schemaAttr) (b, ok bool) + GetDurationOK(schemaAttr) (time.Duration, bool) + GetFloat64OK(schemaAttr) (float64, bool) + GetIntOK(schemaAttr) (int, bool) + GetIntPtr(schemaAttr) *int + GetString(schemaAttr) string + GetStringOK(schemaAttr) (string, bool) + GetStringPtr(schemaAttr) *string + GetStringSlice(attrName schemaAttr) []string BackingType() string } diff --git a/builtin/providers/consul/attr_reader_config.go b/builtin/providers/consul/attr_reader_config.go index 56d88ed50cdf..66e03d9cd760 100644 --- a/builtin/providers/consul/attr_reader_config.go +++ b/builtin/providers/consul/attr_reader_config.go @@ -6,21 +6,21 @@ import ( "github.com/hashicorp/terraform/helper/schema" ) -type _ConfigReader struct { +type configReader struct { d *schema.ResourceData } -func _NewConfigReader(d *schema.ResourceData) *_ConfigReader { - return &_ConfigReader{ +func newConfigReader(d *schema.ResourceData) *configReader { + return &configReader{ d: d, } } -func (r *_ConfigReader) BackingType() string { +func (r *configReader) BackingType() string { return "config" } -func (r *_ConfigReader) GetBool(attrName _SchemaAttr) bool { +func (r *configReader) GetBool(attrName schemaAttr) bool { if v, ok := r.d.GetOk(string(attrName)); ok { return v.(bool) } @@ -28,7 +28,7 @@ func (r *_ConfigReader) GetBool(attrName _SchemaAttr) bool { return false } -func (r *_ConfigReader) GetBoolOK(attrName _SchemaAttr) (b, ok bool) { +func (r *configReader) GetBoolOK(attrName schemaAttr) (b, ok bool) { if v, ok := r.d.GetOk(string(attrName)); ok { return v.(bool), true } @@ -36,7 +36,7 @@ func (r *_ConfigReader) GetBoolOK(attrName _SchemaAttr) (b, ok bool) { return false, false } -func (r *_ConfigReader) GetDurationOK(attrName _SchemaAttr) (time.Duration, bool) { +func (r *configReader) GetDurationOK(attrName schemaAttr) (time.Duration, bool) { if v, ok := r.d.GetOk(string(attrName)); ok { d, err := time.ParseDuration(v.(string)) if err != nil { @@ -48,7 +48,7 @@ func (r *_ConfigReader) GetDurationOK(attrName _SchemaAttr) (time.Duration, bool return time.Duration(0), false } -func (r *_ConfigReader) GetFloat64OK(attrName _SchemaAttr) (float64, bool) { +func (r *configReader) GetFloat64OK(attrName schemaAttr) (float64, bool) { if v, ok := r.d.GetOk(string(attrName)); ok { return v.(float64), true } @@ -56,7 +56,7 @@ func (r *_ConfigReader) GetFloat64OK(attrName _SchemaAttr) (float64, bool) { return 0.0, false } -func (r *_ConfigReader) GetIntOK(attrName _SchemaAttr) (int, bool) { +func (r *configReader) GetIntOK(attrName schemaAttr) (int, bool) { if v, ok := r.d.GetOk(string(attrName)); ok { return v.(int), true } @@ -64,7 +64,7 @@ func (r *_ConfigReader) GetIntOK(attrName _SchemaAttr) (int, bool) { return 0, false } -func (r *_ConfigReader) GetIntPtr(attrName _SchemaAttr) *int { +func (r *configReader) GetIntPtr(attrName schemaAttr) *int { if v, ok := r.d.GetOk(string(attrName)); ok { i := v.(int) return &i @@ -73,7 +73,7 @@ func (r *_ConfigReader) GetIntPtr(attrName _SchemaAttr) *int { return nil } -func (r *_ConfigReader) GetString(attrName _SchemaAttr) string { +func (r *configReader) GetString(attrName schemaAttr) string { if v, ok := r.d.GetOk(string(attrName)); ok { return v.(string) } @@ -81,7 +81,7 @@ func (r *_ConfigReader) GetString(attrName _SchemaAttr) string { return "" } -func (r *_ConfigReader) GetStringOK(attrName _SchemaAttr) (string, bool) { +func (r *configReader) GetStringOK(attrName schemaAttr) (string, bool) { if v, ok := r.d.GetOk(string(attrName)); ok { return v.(string), true } @@ -89,7 +89,7 @@ func (r *_ConfigReader) GetStringOK(attrName _SchemaAttr) (string, bool) { return "", false } -func (r *_ConfigReader) GetStringPtr(attrName _SchemaAttr) *string { +func (r *configReader) GetStringPtr(attrName schemaAttr) *string { if v, ok := r.d.GetOk(string(attrName)); ok { switch v.(type) { case string: @@ -103,7 +103,7 @@ func (r *_ConfigReader) GetStringPtr(attrName _SchemaAttr) *string { return nil } -func (r *_ConfigReader) GetStringSlice(attrName _SchemaAttr) []string { +func (r *configReader) GetStringSlice(attrName schemaAttr) []string { if listRaw, ok := r.d.GetOk(string(attrName)); ok { return listRaw.([]string) } diff --git a/builtin/providers/consul/attr_writer.go b/builtin/providers/consul/attr_writer.go index c1e5d4fe405c..c1785f6f125d 100644 --- a/builtin/providers/consul/attr_writer.go +++ b/builtin/providers/consul/attr_writer.go @@ -2,13 +2,13 @@ package consul import "github.com/hashicorp/terraform/helper/schema" -type _AttrWriter interface { +type attrWriter interface { BackingType() string - SetBool(_SchemaAttr, bool) error - SetFloat64(_SchemaAttr, float64) error - SetList(_SchemaAttr, []interface{}) error - SetMap(_SchemaAttr, map[string]interface{}) error - SetSet(_SchemaAttr, *schema.Set) error - SetString(_SchemaAttr, string) error + SetBool(schemaAttr, bool) error + SetFloat64(schemaAttr, float64) error + SetList(schemaAttr, []interface{}) error + SetMap(schemaAttr, map[string]interface{}) error + SetSet(schemaAttr, *schema.Set) error + SetString(schemaAttr, string) error } diff --git a/builtin/providers/consul/attr_writer_map.go b/builtin/providers/consul/attr_writer_map.go index 1a46e54bc105..071ff52a0f8a 100644 --- a/builtin/providers/consul/attr_writer_map.go +++ b/builtin/providers/consul/attr_writer_map.go @@ -7,21 +7,21 @@ import ( "github.com/hashicorp/terraform/helper/schema" ) -type _AttrWriterMap struct { +type attrWriterMap struct { m map[string]interface{} } -func _NewMapWriter(m map[string]interface{}) *_AttrWriterMap { - return &_AttrWriterMap{ +func newMapWriter(m map[string]interface{}) *attrWriterMap { + return &attrWriterMap{ m: m, } } -func (w *_AttrWriterMap) BackingType() string { +func (w *attrWriterMap) BackingType() string { return "map" } -func (w *_AttrWriterMap) Set(name _SchemaAttr, v interface{}) error { +func (w *attrWriterMap) Set(name schemaAttr, v interface{}) error { switch u := v.(type) { case string: return w.SetString(name, u) @@ -36,35 +36,35 @@ func (w *_AttrWriterMap) Set(name _SchemaAttr, v interface{}) error { } } -func (w *_AttrWriterMap) SetBool(name _SchemaAttr, b bool) error { +func (w *attrWriterMap) SetBool(name schemaAttr, b bool) error { w.m[string(name)] = fmt.Sprintf("%t", b) return nil } -func (w *_AttrWriterMap) SetFloat64(name _SchemaAttr, f float64) error { +func (w *attrWriterMap) SetFloat64(name schemaAttr, f float64) error { w.m[string(name)] = strconv.FormatFloat(f, 'g', -1, 64) return nil } -func (w *_AttrWriterMap) SetList(name _SchemaAttr, l []interface{}) error { +func (w *attrWriterMap) SetList(name schemaAttr, l []interface{}) error { panic(fmt.Sprintf("PROVIDER BUG: Cat set a list within a map for %s", name)) } -func (w *_AttrWriterMap) SetMap(name _SchemaAttr, m map[string]interface{}) error { +func (w *attrWriterMap) SetMap(name schemaAttr, m map[string]interface{}) error { w.m[string(name)] = m return nil panic(fmt.Sprintf("PROVIDER BUG: Cat set a map within a map for %s", name)) } -func (w *_AttrWriterMap) SetSet(name _SchemaAttr, s *schema.Set) error { +func (w *attrWriterMap) SetSet(name schemaAttr, s *schema.Set) error { panic(fmt.Sprintf("PROVIDER BUG: Cat set a set within a map for %s", name)) } -func (w *_AttrWriterMap) SetString(name _SchemaAttr, s string) error { +func (w *attrWriterMap) SetString(name schemaAttr, s string) error { w.m[string(name)] = s return nil } -func (w *_AttrWriterMap) ToMap() map[string]interface{} { +func (w *attrWriterMap) ToMap() map[string]interface{} { return w.m } diff --git a/builtin/providers/consul/attr_writer_state.go b/builtin/providers/consul/attr_writer_state.go index ab11ce095590..561d38d1d27e 100644 --- a/builtin/providers/consul/attr_writer_state.go +++ b/builtin/providers/consul/attr_writer_state.go @@ -2,44 +2,44 @@ package consul import "github.com/hashicorp/terraform/helper/schema" -type _AttrWriterState struct { +type attrWriterState struct { d *schema.ResourceData } -func _NewStateWriter(d *schema.ResourceData) *_AttrWriterState { - return &_AttrWriterState{ +func newStateWriter(d *schema.ResourceData) *attrWriterState { + return &attrWriterState{ d: d, } } -func (w *_AttrWriterState) BackingType() string { +func (w *attrWriterState) BackingType() string { return "state" } -func (w *_AttrWriterState) SetBool(name _SchemaAttr, b bool) error { - return _StateSet(w.d, name, b) +func (w *attrWriterState) SetBool(name schemaAttr, b bool) error { + return stateSet(w.d, name, b) } -func (w *_AttrWriterState) SetID(id string) { +func (w *attrWriterState) SetID(id string) { w.d.SetId(id) } -func (w *_AttrWriterState) SetFloat64(name _SchemaAttr, f float64) error { - return _StateSet(w.d, name, f) +func (w *attrWriterState) SetFloat64(name schemaAttr, f float64) error { + return stateSet(w.d, name, f) } -func (w *_AttrWriterState) SetList(name _SchemaAttr, l []interface{}) error { - return _StateSet(w.d, name, l) +func (w *attrWriterState) SetList(name schemaAttr, l []interface{}) error { + return stateSet(w.d, name, l) } -func (w *_AttrWriterState) SetMap(name _SchemaAttr, m map[string]interface{}) error { - return _StateSet(w.d, name, m) +func (w *attrWriterState) SetMap(name schemaAttr, m map[string]interface{}) error { + return stateSet(w.d, name, m) } -func (w *_AttrWriterState) SetSet(name _SchemaAttr, s *schema.Set) error { - return _StateSet(w.d, name, []interface{}{s}) +func (w *attrWriterState) SetSet(name schemaAttr, s *schema.Set) error { + return stateSet(w.d, name, []interface{}{s}) } -func (w *_AttrWriterState) SetString(name _SchemaAttr, s string) error { - return _StateSet(w.d, name, s) +func (w *attrWriterState) SetString(name schemaAttr, s string) error { + return stateSet(w.d, name, s) } diff --git a/builtin/providers/consul/data_source_consul_agent_self.go b/builtin/providers/consul/data_source_consul_agent_self.go index 319b32f2b1f2..98489267f07b 100644 --- a/builtin/providers/consul/data_source_consul_agent_self.go +++ b/builtin/providers/consul/data_source_consul_agent_self.go @@ -9,810 +9,810 @@ import ( ) const ( - _AgentSelfACLDatacenter _TypeKey = iota - _AgentSelfACLDefaultPolicy - _AgentSelfACLDisableTTL - _AgentSelfACLDownPolicy - _AgentSelfACLEnforceVersion8 - _AgentSelfACLTTL - _AgentSelfAddresses - _AgentSelfAdvertiseAddr - _AgentSelfAdvertiseAddrWAN - _AgentSelfAdvertiseAddrs - _AgentSelfAtlasJoin - _AgentSelfBindAddr - _AgentSelfBootstrap - _AgentSelfBootstrapExpect - _AgentSelfCAFile - _AgentSelfCertFile - _AgentSelfCheckDeregisterIntervalMin - _AgentSelfCheckDisableAnonymousSignature - _AgentSelfCheckDisableRemoteExec - _AgentSelfCheckReapInterval - _AgentSelfCheckUpdateInterval - _AgentSelfClientAddr - _AgentSelfDNSConfig - _AgentSelfDNSRecursors - _AgentSelfDataDir - _AgentSelfDatacenter - _AgentSelfDevMode - _AgentSelfDisableCoordinates - _AgentSelfDisableUpdateCheck - _AgentSelfDomain - _AgentSelfEnableDebug - _AgentSelfEnableSyslog - _AgentSelfEnableUI - _AgentSelfID - _AgentSelfKeyFile - _AgentSelfLeaveOnInt - _AgentSelfLeaveOnTerm - _AgentSelfLogLevel - _AgentSelfName - _AgentSelfPerformance - _AgentSelfPidFile - _AgentSelfPorts - _AgentSelfProtocol - _AgentSelfReconnectTimeoutLAN - _AgentSelfReconnectTimeoutWAN - _AgentSelfRejoinAfterLeave - _AgentSelfRetryJoin - _AgentSelfRetryJoinEC2 - _AgentSelfRetryJoinGCE - _AgentSelfRetryJoinWAN - _AgentSelfRetryMaxAttempts - _AgentSelfRetryMaxAttemptsWAN - _AgentSelfRevision - _AgentSelfSerfLANBindAddr - _AgentSelfSerfWANBindAddr - _AgentSelfServer - _AgentSelfServerName - _AgentSelfSessionTTLMin - _AgentSelfStartJoin - _AgentSelfStartJoinWAN - _AgentSelfSyslogFacility - _AgentSelfTLSMinVersion - _AgentSelfTaggedAddresses - _AgentSelfTelemetry - _AgentSelfTranslateWANAddrs - _AgentSelfUIDir - _AgentSelfUnixSockets - _AgentSelfVerifyIncoming - _AgentSelfVerifyOutgoing - _AgentSelfVerifyServerHostname - _AgentSelfVersion - _AgentSelfVersionPrerelease + agentSelfACLDatacenter typeKey = iota + agentSelfACLDefaultPolicy + agentSelfACLDisableTTL + agentSelfACLDownPolicy + agentSelfACLEnforceVersion8 + agentSelfACLTTL + agentSelfAddresses + agentSelfAdvertiseAddr + agentSelfAdvertiseAddrWAN + agentSelfAdvertiseAddrs + agentSelfAtlasJoin + agentSelfBindAddr + agentSelfBootstrap + agentSelfBootstrapExpect + agentSelfCAFile + agentSelfCertFile + agentSelfCheckDeregisterIntervalMin + agentSelfCheckDisableAnonymousSignature + agentSelfCheckDisableRemoteExec + agentSelfCheckReapInterval + agentSelfCheckUpdateInterval + agentSelfClientAddr + agentSelfDNSConfig + agentSelfDNSRecursors + agentSelfDataDir + agentSelfDatacenter + agentSelfDevMode + agentSelfDisableCoordinates + agentSelfDisableUpdateCheck + agentSelfDomain + agentSelfEnableDebug + agentSelfEnableSyslog + agentSelfEnableUI + agentSelfID + agentSelfKeyFile + agentSelfLeaveOnInt + agentSelfLeaveOnTerm + agentSelfLogLevel + agentSelfName + agentSelfPerformance + agentSelfPidFile + agentSelfPorts + agentSelfProtocol + agentSelfReconnectTimeoutLAN + agentSelfReconnectTimeoutWAN + agentSelfRejoinAfterLeave + agentSelfRetryJoin + agentSelfRetryJoinEC2 + agentSelfRetryJoinGCE + agentSelfRetryJoinWAN + agentSelfRetryMaxAttempts + agentSelfRetryMaxAttemptsWAN + agentSelfRevision + agentSelfSerfLANBindAddr + agentSelfSerfWANBindAddr + agentSelfServer + agentSelfServerName + agentSelfSessionTTLMin + agentSelfStartJoin + agentSelfStartJoinWAN + agentSelfSyslogFacility + agentSelfTLSMinVersion + agentSelfTaggedAddresses + agentSelfTelemetry + agentSelfTranslateWANAddrs + agentSelfUIDir + agentSelfUnixSockets + agentSelfVerifyIncoming + agentSelfVerifyOutgoing + agentSelfVerifyServerHostname + agentSelfVersion + agentSelfVersionPrerelease ) const ( - _AgentSelfDNSAllowStale _TypeKey = iota - _AgentSelfDNSMaxStale - _AgentSelfRecursorTimeout - _AgentSelfDNSDisableCompression - _AgentSelfDNSEnableTruncate - _AgentSelfDNSNodeTTL - _AgentSelfDNSOnlyPassing - _AgentSelfDNSUDPAnswerLimit - _AgentSelfServiceTTL + agentSelfDNSAllowStale typeKey = iota + agentSelfDNSMaxStale + agentSelfRecursorTimeout + agentSelfDNSDisableCompression + agentSelfDNSEnableTruncate + agentSelfDNSNodeTTL + agentSelfDNSOnlyPassing + agentSelfDNSUDPAnswerLimit + agentSelfServiceTTL ) const ( - _AgentSelfPerformanceRaftMultiplier _TypeKey = iota + agentSelfPerformanceRaftMultiplier typeKey = iota ) const ( - _AgentSelfPortsDNS _TypeKey = iota - _AgentSelfPortsHTTP - _AgentSelfPortsHTTPS - _AgentSelfPortsRPC - _AgentSelfPortsSerfLAN - _AgentSelfPortsSerfWAN - _AgentSelfPortsServer + agentSelfPortsDNS typeKey = iota + agentSelfPortsHTTP + agentSelfPortsHTTPS + agentSelfPortsRPC + agentSelfPortsSerfLAN + agentSelfPortsSerfWAN + agentSelfPortsServer ) const ( - _AgentSelfTaggedAddressesLAN _TypeKey = iota - _AgentSelfTaggedAddressesWAN + agentSelfTaggedAddressesLAN typeKey = iota + agentSelfTaggedAddressesWAN ) const ( - _AgentSelfTelemetryCirconusAPIApp _TypeKey = iota - _AgentSelfTelemetryCirconusAPIURL - _AgentSelfTelemetryCirconusBrokerID - _AgentSelfTelemetryCirconusBrokerSelectTag - _AgentSelfTelemetryCirconusCheckDisplayName - _AgentSelfTelemetryCirconusCheckForceMetricActiation - _AgentSelfTelemetryCirconusCheckID - _AgentSelfTelemetryCirconusCheckInstanceID - _AgentSelfTelemetryCirconusCheckSearchTag - _AgentSelfTelemetryCirconusCheckSubmissionURL - _AgentSelfTelemetryCirconusCheckTags - _AgentSelfTelemetryCirconusSubmissionInterval - _AgentSelfTelemetryDisableHostname - _AgentSelfTelemetryDogStatsdAddr - _AgentSelfTelemetryDogStatsdTags - _AgentSelfTelemetryStatsdAddr - _AgentSelfTelemetryStatsiteAddr - _AgentSelfTelemetryStatsitePrefix + agentSelfTelemetryCirconusAPIApp typeKey = iota + agentSelfTelemetryCirconusAPIURL + agentSelfTelemetryCirconusBrokerID + agentSelfTelemetryCirconusBrokerSelectTag + agentSelfTelemetryCirconusCheckDisplayName + agentSelfTelemetryCirconusCheckForceMetricActiation + agentSelfTelemetryCirconusCheckID + agentSelfTelemetryCirconusCheckInstanceID + agentSelfTelemetryCirconusCheckSearchTag + agentSelfTelemetryCirconusCheckSubmissionURL + agentSelfTelemetryCirconusCheckTags + agentSelfTelemetryCirconusSubmissionInterval + agentSelfTelemetryDisableHostname + agentSelfTelemetryDogStatsdAddr + agentSelfTelemetryDogStatsdTags + agentSelfTelemetryStatsdAddr + agentSelfTelemetryStatsiteAddr + agentSelfTelemetryStatsitePrefix ) // Schema for consul's /v1/agent/self endpoint -var _AgentSelfMap = map[_TypeKey]*_TypeEntry{ - _AgentSelfACLDatacenter: { +var agentSelfMap = map[typeKey]*typeEntry{ + agentSelfACLDatacenter: { APIName: "ACLDatacenter", SchemaName: "acl_datacenter", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfACLDefaultPolicy: { + agentSelfACLDefaultPolicy: { APIName: "ACLDefaultPolicy", SchemaName: "acl_default_policy", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfACLDisableTTL: { + agentSelfACLDisableTTL: { APIName: "ACLDisabledTTL", SchemaName: "acl_disable_ttl", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfACLDownPolicy: { + agentSelfACLDownPolicy: { APIName: "ACLDownPolicy", SchemaName: "acl_down_policy", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfACLEnforceVersion8: { + agentSelfACLEnforceVersion8: { APIName: "ACLEnforceVersion8", SchemaName: "acl_enforce_version_8", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfACLTTL: { + agentSelfACLTTL: { APIName: "ACLTTL", SchemaName: "acl_ttl", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfAddresses: { + agentSelfAddresses: { APIName: "Addresses", SchemaName: "addresses", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeMap, }, - _AgentSelfAdvertiseAddr: { + agentSelfAdvertiseAddr: { APIName: "AdvertiseAddr", SchemaName: "advertise_addr", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfAdvertiseAddrs: { + agentSelfAdvertiseAddrs: { APIName: "AdvertiseAddrs", SchemaName: "advertise_addrs", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeMap, }, - _AgentSelfAdvertiseAddrWAN: { + agentSelfAdvertiseAddrWAN: { APIName: "AdvertiseAddrWan", SchemaName: "advertise_addr_wan", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, // Omitting the following since they've been depreciated: // // "AtlasInfrastructure": "", // "AtlasEndpoint": "", - _AgentSelfAtlasJoin: { + agentSelfAtlasJoin: { APIName: "AtlasJoin", SchemaName: "atlas_join", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfBindAddr: { + agentSelfBindAddr: { APIName: "BindAddr", SchemaName: "bind_addr", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfBootstrap: { + agentSelfBootstrap: { APIName: "Bootstrap", SchemaName: "bootstrap", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfBootstrapExpect: { + agentSelfBootstrapExpect: { APIName: "BootstrapExpect", SchemaName: "bootstrap_expect", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfCAFile: { + agentSelfCAFile: { APIName: "CAFile", SchemaName: "ca_file", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfCertFile: { + agentSelfCertFile: { APIName: "CertFile", SchemaName: "cert_file", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfCheckDeregisterIntervalMin: { + agentSelfCheckDeregisterIntervalMin: { APIName: "CheckDeregisterIntervalMin", SchemaName: "check_deregister_interval_min", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfCheckDisableAnonymousSignature: { + agentSelfCheckDisableAnonymousSignature: { APIName: "DisableAnonymousSignature", SchemaName: "disable_anonymous_signature", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfCheckDisableRemoteExec: { + agentSelfCheckDisableRemoteExec: { APIName: "DisableRemoteExec", SchemaName: "disable_remote_exec", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfCheckReapInterval: { + agentSelfCheckReapInterval: { APIName: "CheckReapInterval", SchemaName: "check_reap_interval", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfCheckUpdateInterval: { + agentSelfCheckUpdateInterval: { APIName: "CheckUpdateInterval", SchemaName: "check_update_interval", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfClientAddr: { + agentSelfClientAddr: { APIName: "ClientAddr", SchemaName: "client_addr", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfDNSConfig: { + agentSelfDNSConfig: { APIName: "DNSConfig", SchemaName: "dns_config", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeMap, - SetMembers: map[_TypeKey]*_TypeEntry{ - _AgentSelfDNSAllowStale: { + SetMembers: map[typeKey]*typeEntry{ + agentSelfDNSAllowStale: { APIName: "AllowStale", SchemaName: "allow_stale", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfDNSDisableCompression: { + agentSelfDNSDisableCompression: { APIName: "DisableCompression", SchemaName: "disable_compression", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfDNSEnableTruncate: { + agentSelfDNSEnableTruncate: { APIName: "EnableTruncate", SchemaName: "enable_truncate", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfDNSMaxStale: { + agentSelfDNSMaxStale: { APIName: "MaxStale", SchemaName: "max_stale", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfDNSNodeTTL: { + agentSelfDNSNodeTTL: { APIName: "NodeTTL", SchemaName: "node_ttl", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfDNSOnlyPassing: { + agentSelfDNSOnlyPassing: { APIName: "OnlyPassing", SchemaName: "only_passing", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfRecursorTimeout: { + agentSelfRecursorTimeout: { APIName: "RecursorTimeout", SchemaName: "recursor_timeout", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfServiceTTL: { + agentSelfServiceTTL: { APIName: "ServiceTTL", SchemaName: "service_ttl", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfDNSUDPAnswerLimit: { + agentSelfDNSUDPAnswerLimit: { APIName: "UDPAnswerLimit", SchemaName: "udp_answer_limit", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, }, }, - _AgentSelfDataDir: { + agentSelfDataDir: { APIName: "DataDir", SchemaName: "data_dir", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfDatacenter: { + agentSelfDatacenter: { APIName: "Datacenter", SchemaName: "datacenter", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfDevMode: { + agentSelfDevMode: { APIName: "DevMode", SchemaName: "dev_mode", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfDisableCoordinates: { + agentSelfDisableCoordinates: { APIName: "DisableCoordinates", SchemaName: "coordinates", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfDisableUpdateCheck: { + agentSelfDisableUpdateCheck: { APIName: "DisableUpdateCheck", SchemaName: "update_check", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfDNSRecursors: { + agentSelfDNSRecursors: { APIName: "DNSRecursors", - APIAliases: []_APIAttr{"DNSRecursor"}, + APIAliases: []apiAttr{"DNSRecursor"}, SchemaName: "dns_recursors", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeList, }, - _AgentSelfDomain: { + agentSelfDomain: { APIName: "Domain", SchemaName: "domain", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfEnableDebug: { + agentSelfEnableDebug: { APIName: "EnableDebug", SchemaName: "debug", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfEnableSyslog: { + agentSelfEnableSyslog: { APIName: "EnableSyslog", SchemaName: "syslog", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfEnableUI: { + agentSelfEnableUI: { APIName: "EnableUi", SchemaName: "ui", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, // "HTTPAPIResponseHeaders": nil, - _AgentSelfID: { + agentSelfID: { APIName: "NodeID", SchemaName: "id", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, ValidateFuncs: []interface{}{ - _ValidateRegexp(`(?i)^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$`), + validateRegexp(`(?i)^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$`), }, - APITest: _APITestID, - APIToState: _APIToStateID, + APITest: apiTestID, + APIToState: apiToStateID, }, - _AgentSelfKeyFile: { + agentSelfKeyFile: { APIName: "KeyFile", SchemaName: "key_file", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfLeaveOnInt: { + agentSelfLeaveOnInt: { APIName: "SkipLeaveOnInt", SchemaName: "leave_on_int", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, - APITest: _APITestBool, - APIToState: _NegateBoolToState(_APIToStateBool), + APITest: apiTestBool, + APIToState: negateBoolToState(apiToStateBool), }, - _AgentSelfLeaveOnTerm: { + agentSelfLeaveOnTerm: { APIName: "LeaveOnTerm", SchemaName: "leave_on_term", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfLogLevel: { + agentSelfLogLevel: { APIName: "LogLevel", SchemaName: "log_level", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfName: { + agentSelfName: { APIName: "NodeName", SchemaName: "name", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfPerformance: { + agentSelfPerformance: { APIName: "Performance", SchemaName: "performance", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeMap, - SetMembers: map[_TypeKey]*_TypeEntry{ - _AgentSelfPerformanceRaftMultiplier: { + SetMembers: map[typeKey]*typeEntry{ + agentSelfPerformanceRaftMultiplier: { APIName: "RaftMultiplier", SchemaName: "raft_multiplier", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, }, }, - _AgentSelfPidFile: { + agentSelfPidFile: { APIName: "PidFile", SchemaName: "pid_file", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfPorts: { + agentSelfPorts: { APIName: "Ports", SchemaName: "ports", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeMap, - SetMembers: map[_TypeKey]*_TypeEntry{ - _AgentSelfPortsDNS: { + SetMembers: map[typeKey]*typeEntry{ + agentSelfPortsDNS: { APIName: "DNS", SchemaName: "dns", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfPortsHTTP: { + agentSelfPortsHTTP: { APIName: "HTTP", SchemaName: "http", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfPortsHTTPS: { + agentSelfPortsHTTPS: { APIName: "HTTPS", SchemaName: "https", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfPortsRPC: { + agentSelfPortsRPC: { APIName: "RPC", SchemaName: "rpc", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfPortsSerfLAN: { + agentSelfPortsSerfLAN: { APIName: "SerfLan", SchemaName: "serf_lan", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfPortsSerfWAN: { + agentSelfPortsSerfWAN: { APIName: "SerfWan", SchemaName: "serf_wan", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfPortsServer: { + agentSelfPortsServer: { APIName: "Server", SchemaName: "server", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, }, }, - _AgentSelfProtocol: { + agentSelfProtocol: { APIName: "Protocol", SchemaName: "protocol", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfReconnectTimeoutLAN: { + agentSelfReconnectTimeoutLAN: { APIName: "ReconnectTimeoutLan", SchemaName: "reconnect_timeout_lan", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfReconnectTimeoutWAN: { + agentSelfReconnectTimeoutWAN: { APIName: "ReconnectTimeoutWan", SchemaName: "reconnect_timeout_wan", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfRejoinAfterLeave: { + agentSelfRejoinAfterLeave: { APIName: "RejoinAfterLeave", SchemaName: "rejoin_after_leave", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, // "RetryIntervalWanRaw": "", - _AgentSelfRetryJoin: { + agentSelfRetryJoin: { APIName: "RetryJoin", SchemaName: "retry_join", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeList, }, - _AgentSelfRetryJoinWAN: { + agentSelfRetryJoinWAN: { APIName: "RetryJoinWan", SchemaName: "retry_join_wan", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeList, }, - _AgentSelfRetryMaxAttempts: { + agentSelfRetryMaxAttempts: { APIName: "RetryMaxAttempts", SchemaName: "retry_max_attempts", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfRetryMaxAttemptsWAN: { + agentSelfRetryMaxAttemptsWAN: { APIName: "RetryMaxAttemptsWan", SchemaName: "retry_max_attempts_wan", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfRetryJoinEC2: { + agentSelfRetryJoinEC2: { APIName: "RetryJoinEC2", SchemaName: "retry_join_ec2", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeMap, }, - _AgentSelfRetryJoinGCE: { + agentSelfRetryJoinGCE: { APIName: "RetryJoinGCE", SchemaName: "retry_join_GCE", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeMap, }, - _AgentSelfRevision: { + agentSelfRevision: { APIName: "Revision", SchemaName: "revision", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfSerfLANBindAddr: { + agentSelfSerfLANBindAddr: { APIName: "SerfLanBindAddr", SchemaName: "serf_lan_bind_addr", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfSerfWANBindAddr: { + agentSelfSerfWANBindAddr: { APIName: "SerfWanBindAddr", SchemaName: "serf_wan_bind_addr", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfServer: { + agentSelfServer: { APIName: "Server", SchemaName: "server", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfServerName: { + agentSelfServerName: { APIName: "ServerName", SchemaName: "server_name", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfSessionTTLMin: { + agentSelfSessionTTLMin: { APIName: "SessionTTLMin", SchemaName: "session_ttl_min", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeFloat, }, - _AgentSelfStartJoin: { + agentSelfStartJoin: { APIName: "StartJoin", SchemaName: "start_join", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeList, }, - _AgentSelfStartJoinWAN: { + agentSelfStartJoinWAN: { APIName: "StartJoinWan", SchemaName: "start_join_wan", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeList, }, - _AgentSelfSyslogFacility: { + agentSelfSyslogFacility: { APIName: "SyslogFacility", SchemaName: "syslog_facility", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTaggedAddresses: { + agentSelfTaggedAddresses: { APIName: "TaggedAddresses", SchemaName: "tagged_addresses", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeMap, - SetMembers: map[_TypeKey]*_TypeEntry{ - _AgentSelfTaggedAddressesLAN: { + SetMembers: map[typeKey]*typeEntry{ + agentSelfTaggedAddressesLAN: { APIName: "LAN", SchemaName: "lan", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTaggedAddressesWAN: { + agentSelfTaggedAddressesWAN: { APIName: "WAN", SchemaName: "wan", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, }, }, - _AgentSelfTelemetry: { + agentSelfTelemetry: { APIName: "Telemetry", SchemaName: "telemetry", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeMap, - SetMembers: map[_TypeKey]*_TypeEntry{ - _AgentSelfTelemetryCirconusAPIApp: { + SetMembers: map[typeKey]*typeEntry{ + agentSelfTelemetryCirconusAPIApp: { APIName: "CirconusAPIApp", SchemaName: "circonus_api_app", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryCirconusAPIURL: { + agentSelfTelemetryCirconusAPIURL: { APIName: "CirconusAPIURL", SchemaName: "circonus_api_url", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryCirconusBrokerID: { + agentSelfTelemetryCirconusBrokerID: { APIName: "CirconusBrokerID", SchemaName: "circonus_broker_id", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryCirconusBrokerSelectTag: { + agentSelfTelemetryCirconusBrokerSelectTag: { APIName: "CirconusBrokerSelectTag", SchemaName: "circonus_broker_select_tag", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryCirconusCheckDisplayName: { + agentSelfTelemetryCirconusCheckDisplayName: { APIName: "CirconusCheckDisplayName", SchemaName: "circonus_check_display_name", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryCirconusCheckForceMetricActiation: { + agentSelfTelemetryCirconusCheckForceMetricActiation: { APIName: "CirconusCheckForceMetricActivation", SchemaName: "circonus_check_force_metric_activation", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryCirconusCheckID: { + agentSelfTelemetryCirconusCheckID: { APIName: "CirconusCheckID", SchemaName: "circonus_check_id", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryCirconusCheckInstanceID: { + agentSelfTelemetryCirconusCheckInstanceID: { APIName: "CirconusCheckInstanceID", SchemaName: "circonus_check_instance_id", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryCirconusCheckSearchTag: { + agentSelfTelemetryCirconusCheckSearchTag: { APIName: "CirconusCheckSearchTag", SchemaName: "circonus_check_search_tag", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryCirconusCheckSubmissionURL: { + agentSelfTelemetryCirconusCheckSubmissionURL: { APIName: "CirconusCheckSubmissionURL", SchemaName: "circonus_check_submission_url", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryCirconusCheckTags: { + agentSelfTelemetryCirconusCheckTags: { APIName: "CirconusCheckTags", SchemaName: "circonus_check_tags", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryCirconusSubmissionInterval: { + agentSelfTelemetryCirconusSubmissionInterval: { APIName: "CirconusSubmissionInterval", SchemaName: "circonus_submission_interval", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryDisableHostname: { + agentSelfTelemetryDisableHostname: { APIName: "DisableHostname", SchemaName: "disable_hostname", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfTelemetryDogStatsdAddr: { + agentSelfTelemetryDogStatsdAddr: { APIName: "DogStatsdAddr", SchemaName: "dog_statsd_addr", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryDogStatsdTags: { + agentSelfTelemetryDogStatsdTags: { APIName: "DogStatsdTags", SchemaName: "dog_statsd_tags", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryStatsdAddr: { + agentSelfTelemetryStatsdAddr: { APIName: "StatsdTags", SchemaName: "statsd_tags", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryStatsiteAddr: { + agentSelfTelemetryStatsiteAddr: { APIName: "StatsiteAddr", SchemaName: "statsite_addr", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTelemetryStatsitePrefix: { + agentSelfTelemetryStatsitePrefix: { APIName: "StatsitePrefix", SchemaName: "statsite_prefix", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, }, }, - _AgentSelfTLSMinVersion: { + agentSelfTLSMinVersion: { APIName: "TLSMinVersion", SchemaName: "tls_min_version", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfTranslateWANAddrs: { + agentSelfTranslateWANAddrs: { APIName: "TranslateWanAddrs", SchemaName: "translate_wan_addrs", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfUIDir: { + agentSelfUIDir: { APIName: "UiDir", SchemaName: "ui_dir", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfUnixSockets: { + agentSelfUnixSockets: { APIName: "UnixSockets", SchemaName: "unix_sockets", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeMap, }, - _AgentSelfVerifyIncoming: { + agentSelfVerifyIncoming: { APIName: "VerifyIncoming", SchemaName: "verify_incoming", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfVerifyServerHostname: { + agentSelfVerifyServerHostname: { APIName: "VerifyServerHostname", SchemaName: "verify_server_hostname", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfVerifyOutgoing: { + agentSelfVerifyOutgoing: { APIName: "VerifyOutgoing", SchemaName: "verify_outgoing", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeBool, }, - _AgentSelfVersion: { + agentSelfVersion: { APIName: "Version", SchemaName: "version", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, - _AgentSelfVersionPrerelease: { + agentSelfVersionPrerelease: { APIName: "VersionPrerelease", SchemaName: "version_prerelease", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, }, // "Watches": nil, @@ -821,7 +821,7 @@ var _AgentSelfMap = map[_TypeKey]*_TypeEntry{ func dataSourceConsulAgentSelf() *schema.Resource { return &schema.Resource{ Read: dataSourceConsulAgentSelfRead, - Schema: _TypeEntryMapToSchema(_AgentSelfMap), + Schema: typeEntryMapToSchema(agentSelfMap), } } @@ -832,19 +832,19 @@ func dataSourceConsulAgentSelfRead(d *schema.ResourceData, meta interface{}) err return err } - const _APIAgentConfig = "Config" - cfg, ok := info[_APIAgentConfig] + const apiAgentConfig = "Config" + cfg, ok := info[apiAgentConfig] if !ok { - return fmt.Errorf("No %s info available within provider's agent/self endpoint", _APIAgentConfig) + return fmt.Errorf("No %s info available within provider's agent/self endpoint", apiAgentConfig) } // TODO(sean@): It'd be nice if this data source had a way of filtering out // irrelevant data so only the important bits are persisted in the state file. // Something like an attribute mask or even a regexp of matching schema names // would be sufficient in the most basic case. Food for thought. - dataSourceWriter := _NewStateWriter(d) + dataSourceWriter := newStateWriter(d) - for k, e := range _AgentSelfMap { + for k, e := range agentSelfMap { apiTest := e.APITest if apiTest == nil { apiTest = e.LookupDefaultTypeHandler().APITest diff --git a/builtin/providers/consul/data_source_consul_catalog_nodes.go b/builtin/providers/consul/data_source_consul_catalog_nodes.go index 8bb707c2d669..a1d8d176b603 100644 --- a/builtin/providers/consul/data_source_consul_catalog_nodes.go +++ b/builtin/providers/consul/data_source_consul_catalog_nodes.go @@ -11,41 +11,41 @@ import ( // Top-level consul_catalog_nodes attributes const ( - _CatalogNodes _TypeKey = iota - _CatalogNodesAllowStale - _CatalogNodesDatacenter - _CatalogNodesNear - _CatalogNodesRequireConsistent - _CatalogNodesToken - _CatalogNodesWaitIndex - _CatalogNodesWaitTime + catalogNodes typeKey = iota + catalogNodesAllowStale + catalogNodesDatacenter + catalogNodesNear + catalogNodesRequireConsistent + catalogNodesToken + catalogNodesWaitIndex + catalogNodesWaitTime ) // node.* attributes const ( - _CatalogNodeID _TypeKey = iota - _CatalogNodeName - _CatalogNodeAddress - _CatalogNodeTaggedAddresses - _CatalogNodeMeta + catalogNodeID typeKey = iota + catalogNodeName + catalogNodeAddress + catalogNodeTaggedAddresses + catalogNodeMeta ) // node.tagged_addresses.* attributes const ( - _CatalogNodeTaggedAddressesLAN _TypeKey = iota - _CatalogNodeTaggedAddressesWAN + catalogNodeTaggedAddressesLAN typeKey = iota + catalogNodeTaggedAddressesWAN ) -var _CatalogNodeAttrs = map[_TypeKey]*_TypeEntry{ - _CatalogNodeID: { +var catalogNodeAttrs = map[typeKey]*typeEntry{ + catalogNodeID: { APIName: "ID", SchemaName: "id", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, ValidateFuncs: []interface{}{ - _ValidateRegexp(`^[\S]+$`), + validateRegexp(`^[\S]+$`), }, - APITest: func(e *_TypeEntry, v interface{}) (interface{}, bool) { + APITest: func(e *typeEntry, v interface{}) (interface{}, bool) { node := v.(*consulapi.Node) if id := node.ID; id != "" { @@ -61,15 +61,15 @@ var _CatalogNodeAttrs = map[_TypeKey]*_TypeEntry{ return "", false }, }, - _CatalogNodeName: { + catalogNodeName: { APIName: "Name", SchemaName: "name", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, ValidateFuncs: []interface{}{ - _ValidateRegexp(`^[\S]+$`), + validateRegexp(`^[\S]+$`), }, - APITest: func(e *_TypeEntry, v interface{}) (interface{}, bool) { + APITest: func(e *typeEntry, v interface{}) (interface{}, bool) { node := v.(*consulapi.Node) if name := node.Node; name != "" { @@ -79,12 +79,12 @@ var _CatalogNodeAttrs = map[_TypeKey]*_TypeEntry{ return "", false }, }, - _CatalogNodeAddress: { + catalogNodeAddress: { APIName: "Address", SchemaName: "address", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, - APITest: func(e *_TypeEntry, v interface{}) (interface{}, bool) { + APITest: func(e *typeEntry, v interface{}) (interface{}, bool) { node := v.(*consulapi.Node) if addr := node.Address; addr != "" { @@ -94,18 +94,18 @@ var _CatalogNodeAttrs = map[_TypeKey]*_TypeEntry{ return "", false }, }, - _CatalogNodeTaggedAddresses: { + catalogNodeTaggedAddresses: { APIName: "TaggedAddresses", SchemaName: "tagged_addresses", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeMap, - SetMembers: map[_TypeKey]*_TypeEntry{ - _CatalogNodeTaggedAddressesLAN: { + SetMembers: map[typeKey]*typeEntry{ + catalogNodeTaggedAddressesLAN: { APIName: "LAN", SchemaName: "lan", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, - APITest: func(e *_TypeEntry, v interface{}) (interface{}, bool) { + APITest: func(e *typeEntry, v interface{}) (interface{}, bool) { m := v.(map[string]string) if addr, found := m[string(e.SchemaName)]; found { @@ -115,12 +115,12 @@ var _CatalogNodeAttrs = map[_TypeKey]*_TypeEntry{ return nil, false }, }, - _CatalogNodeTaggedAddressesWAN: { + catalogNodeTaggedAddressesWAN: { APIName: "WAN", SchemaName: "wan", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeString, - APITest: func(e *_TypeEntry, v interface{}) (interface{}, bool) { + APITest: func(e *typeEntry, v interface{}) (interface{}, bool) { m := v.(map[string]string) if addr, found := m[string(e.SchemaName)]; found { @@ -131,26 +131,26 @@ var _CatalogNodeAttrs = map[_TypeKey]*_TypeEntry{ }, }, }, - APITest: func(e *_TypeEntry, v interface{}) (interface{}, bool) { + APITest: func(e *typeEntry, v interface{}) (interface{}, bool) { node := v.(*consulapi.Node) if addrs := node.TaggedAddresses; len(addrs) > 0 { - return _MapStringToMapInterface(addrs), true + return mapStringToMapInterface(addrs), true } return nil, false }, }, - _CatalogNodeMeta: { + catalogNodeMeta: { APIName: "Meta", SchemaName: "meta", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeMap, - APITest: func(e *_TypeEntry, v interface{}) (interface{}, bool) { + APITest: func(e *typeEntry, v interface{}) (interface{}, bool) { node := v.(*consulapi.Node) if meta := node.Meta; len(meta) > 0 { - return _MapStringToMapInterface(meta), true + return mapStringToMapInterface(meta), true } return nil, false @@ -158,13 +158,13 @@ var _CatalogNodeAttrs = map[_TypeKey]*_TypeEntry{ }, } -var _CatalogNodesAttrs = map[_TypeKey]*_TypeEntry{ - _CatalogNodesAllowStale: { +var catalogNodesAttrs = map[typeKey]*typeEntry{ + catalogNodesAllowStale: { SchemaName: "allow_stale", - Source: _SourceLocalFilter, + Source: sourceLocalFilter, Type: schema.TypeBool, Default: true, - ConfigRead: func(e *_TypeEntry, r _AttrReader) (interface{}, bool) { + ConfigRead: func(e *typeEntry, r attrReader) (interface{}, bool) { b, ok := r.GetBoolOK(e.SchemaName) if !ok { return nil, false @@ -172,18 +172,18 @@ var _CatalogNodesAttrs = map[_TypeKey]*_TypeEntry{ return b, true }, - ConfigUse: func(e *_TypeEntry, v interface{}, target interface{}) error { + ConfigUse: func(e *typeEntry, v interface{}, target interface{}) error { b := v.(bool) queryOpts := target.(*consulapi.QueryOptions) queryOpts.AllowStale = b return nil }, }, - _CatalogNodesDatacenter: { + catalogNodesDatacenter: { SchemaName: "datacenter", - Source: _SourceLocalFilter, + Source: sourceLocalFilter, Type: schema.TypeString, - ConfigRead: func(e *_TypeEntry, r _AttrReader) (interface{}, bool) { + ConfigRead: func(e *typeEntry, r attrReader) (interface{}, bool) { s, ok := r.GetStringOK(e.SchemaName) if !ok { return nil, false @@ -191,18 +191,18 @@ var _CatalogNodesAttrs = map[_TypeKey]*_TypeEntry{ return s, true }, - ConfigUse: func(e *_TypeEntry, v interface{}, target interface{}) error { + ConfigUse: func(e *typeEntry, v interface{}, target interface{}) error { s := v.(string) queryOpts := target.(*consulapi.QueryOptions) queryOpts.Datacenter = s return nil }, }, - _CatalogNodesNear: { + catalogNodesNear: { SchemaName: "near", - Source: _SourceLocalFilter, + Source: sourceLocalFilter, Type: schema.TypeString, - ConfigRead: func(e *_TypeEntry, r _AttrReader) (interface{}, bool) { + ConfigRead: func(e *typeEntry, r attrReader) (interface{}, bool) { s, ok := r.GetStringOK(e.SchemaName) if !ok { return nil, false @@ -210,25 +210,25 @@ var _CatalogNodesAttrs = map[_TypeKey]*_TypeEntry{ return s, true }, - ConfigUse: func(e *_TypeEntry, v interface{}, target interface{}) error { + ConfigUse: func(e *typeEntry, v interface{}, target interface{}) error { s := v.(string) queryOpts := target.(*consulapi.QueryOptions) queryOpts.Near = s return nil }, }, - _CatalogNodes: { + catalogNodes: { SchemaName: "nodes", - Source: _SourceAPIResult, + Source: sourceAPIResult, Type: schema.TypeList, - ListSchema: _CatalogNodeAttrs, + ListSchema: catalogNodeAttrs, }, - _CatalogNodesRequireConsistent: { + catalogNodesRequireConsistent: { SchemaName: "require_consistent", - Source: _SourceLocalFilter, + Source: sourceLocalFilter, Type: schema.TypeBool, Default: false, - ConfigRead: func(e *_TypeEntry, r _AttrReader) (interface{}, bool) { + ConfigRead: func(e *typeEntry, r attrReader) (interface{}, bool) { b, ok := r.GetBoolOK(e.SchemaName) if !ok { return nil, false @@ -236,18 +236,18 @@ var _CatalogNodesAttrs = map[_TypeKey]*_TypeEntry{ return b, true }, - ConfigUse: func(e *_TypeEntry, v interface{}, target interface{}) error { + ConfigUse: func(e *typeEntry, v interface{}, target interface{}) error { b := v.(bool) queryOpts := target.(*consulapi.QueryOptions) queryOpts.RequireConsistent = b return nil }, }, - _CatalogNodesToken: { + catalogNodesToken: { SchemaName: "token", - Source: _SourceLocalFilter, + Source: sourceLocalFilter, Type: schema.TypeString, - ConfigRead: func(e *_TypeEntry, r _AttrReader) (interface{}, bool) { + ConfigRead: func(e *typeEntry, r attrReader) (interface{}, bool) { s, ok := r.GetStringOK(e.SchemaName) if !ok { return nil, false @@ -255,21 +255,21 @@ var _CatalogNodesAttrs = map[_TypeKey]*_TypeEntry{ return s, true }, - ConfigUse: func(e *_TypeEntry, v interface{}, target interface{}) error { + ConfigUse: func(e *typeEntry, v interface{}, target interface{}) error { s := v.(string) queryOpts := target.(*consulapi.QueryOptions) queryOpts.Token = s return nil }, }, - _CatalogNodesWaitIndex: { + catalogNodesWaitIndex: { SchemaName: "wait_index", - Source: _SourceLocalFilter, + Source: sourceLocalFilter, Type: schema.TypeInt, ValidateFuncs: []interface{}{ - _ValidateIntMin(0), + validateIntMin(0), }, - ConfigRead: func(e *_TypeEntry, r _AttrReader) (interface{}, bool) { + ConfigRead: func(e *typeEntry, r attrReader) (interface{}, bool) { i, ok := r.GetIntOK(e.SchemaName) if !ok { return nil, false @@ -277,21 +277,21 @@ var _CatalogNodesAttrs = map[_TypeKey]*_TypeEntry{ return uint64(i), true }, - ConfigUse: func(e *_TypeEntry, v interface{}, target interface{}) error { + ConfigUse: func(e *typeEntry, v interface{}, target interface{}) error { i := v.(uint64) queryOpts := target.(*consulapi.QueryOptions) queryOpts.WaitIndex = i return nil }, }, - _CatalogNodesWaitTime: { + catalogNodesWaitTime: { SchemaName: "wait_time", - Source: _SourceLocalFilter, + Source: sourceLocalFilter, Type: schema.TypeString, ValidateFuncs: []interface{}{ - _ValidateDurationMin("0ns"), + validateDurationMin("0ns"), }, - ConfigRead: func(e *_TypeEntry, r _AttrReader) (interface{}, bool) { + ConfigRead: func(e *typeEntry, r attrReader) (interface{}, bool) { d, ok := r.GetDurationOK(e.SchemaName) if !ok { return nil, false @@ -299,7 +299,7 @@ var _CatalogNodesAttrs = map[_TypeKey]*_TypeEntry{ return d, true }, - ConfigUse: func(e *_TypeEntry, v interface{}, target interface{}) error { + ConfigUse: func(e *typeEntry, v interface{}, target interface{}) error { d := v.(time.Duration) queryOpts := target.(*consulapi.QueryOptions) queryOpts.WaitTime = d @@ -311,7 +311,7 @@ var _CatalogNodesAttrs = map[_TypeKey]*_TypeEntry{ func dataSourceConsulCatalogNodes() *schema.Resource { return &schema.Resource{ Read: dataSourceConsulCatalogNodesRead, - Schema: _TypeEntryMapToSchema(_CatalogNodesAttrs), + Schema: typeEntryMapToSchema(catalogNodesAttrs), } } @@ -327,12 +327,12 @@ func dataSourceConsulCatalogNodesRead(d *schema.ResourceData, meta interface{}) Datacenter: dc, } - cfgReader := _NewConfigReader(d) + cfgReader := newConfigReader(d) // Construct the query options - for _, e := range _CatalogNodesAttrs[_CatalogNodes].ListSchema { + for _, e := range catalogNodesAttrs[catalogNodes].ListSchema { // Only evaluate attributes that impact the state - if e.Source&_SourceLocalFilter == 0 { + if e.Source&sourceLocalFilter == 0 { continue } @@ -357,12 +357,12 @@ func dataSourceConsulCatalogNodesRead(d *schema.ResourceData, meta interface{}) l := make([]interface{}, 0, len(nodes)) for _, node := range nodes { - mWriter := _NewMapWriter(make(map[string]interface{}, len(_CatalogNodeAttrs))) + mWriter := newMapWriter(make(map[string]interface{}, len(catalogNodeAttrs))) // /v1/catalog/nodes returns a list of node objects - for _, e := range _CatalogNodesAttrs[_CatalogNodes].ListSchema { + for _, e := range catalogNodesAttrs[catalogNodes].ListSchema { // Only evaluate attributes that impact the state - if e.Source&_ModifyState == 0 { + if e.Source&modifyState == 0 { continue } @@ -378,9 +378,9 @@ func dataSourceConsulCatalogNodesRead(d *schema.ResourceData, meta interface{}) l = append(l, mWriter.ToMap()) } - dataSourceWriter := _NewStateWriter(d) - dataSourceWriter.SetList(_CatalogNodesAttrs[_CatalogNodes].SchemaName, l) - dataSourceWriter.SetString(_CatalogNodesAttrs[_CatalogNodesDatacenter].SchemaName, dc) + dataSourceWriter := newStateWriter(d) + dataSourceWriter.SetList(catalogNodesAttrs[catalogNodes].SchemaName, l) + dataSourceWriter.SetString(catalogNodesAttrs[catalogNodesDatacenter].SchemaName, dc) const idKeyFmt = "catalog-nodes-%s" dataSourceWriter.SetID(fmt.Sprintf(idKeyFmt, dc)) diff --git a/builtin/providers/consul/utils.go b/builtin/providers/consul/utils.go index a23429b2b18c..d544c9850cc5 100644 --- a/builtin/providers/consul/utils.go +++ b/builtin/providers/consul/utils.go @@ -13,132 +13,132 @@ import ( "github.com/hashicorp/terraform/helper/schema" ) -// _APIAttr is the type used for constants representing well known keys within +// apiAttr is the type used for constants representing well known keys within // the API that are transmitted back to a resource over an API. -type _APIAttr string +type apiAttr string -// _SchemaAttr is the type used for constants representing well known keys +// schemaAttr is the type used for constants representing well known keys // within the schema for a resource. -type _SchemaAttr string +type schemaAttr string -// _SourceFlags represent the ways in which an attribute can be written. Some +// sourceFlags represent the ways in which an attribute can be written. Some // sources are mutually exclusive, yet other flag combinations are composable. -type _SourceFlags int +type sourceFlags int -// _TypeKey is the lookup mechanism for the generated schema. -type _TypeKey int +// typeKey is the lookup mechanism for the generated schema. +type typeKey int // An array of inputs used as typed arguments and converted from their type into // function objects that are dynamically constructed and executed. -type _ValidatorInputs []interface{} +type validatorInputs []interface{} -// _ValidateDurationMin is the minimum duration to accept as input -type _ValidateDurationMin string +// validateDurationMin is the minimum duration to accept as input +type validateDurationMin string -// _ValidateIntMin is the minimum integer value to accept as input -type _ValidateIntMin int +// validateIntMin is the minimum integer value to accept as input +type validateIntMin int -// _ValidateRegexp is a regexp pattern to use to validate schema input. -type _ValidateRegexp string +// validateRegexp is a regexp pattern to use to validate schema input. +type validateRegexp string const ( - // _SourceUserRequired indicates the parameter must be provided by the user in + // sourceUserRequired indicates the parameter must be provided by the user in // their configuration. - _SourceUserRequired _SourceFlags = 1 << iota + sourceUserRequired sourceFlags = 1 << iota - // _SourceUserOptional indicates the parameter may optionally be specified by + // sourceUserOptional indicates the parameter may optionally be specified by // the user in their configuration. - _SourceUserOptional + sourceUserOptional - // _SourceAPIResult indicates the parameter may only be set by the return of + // sourceAPIResult indicates the parameter may only be set by the return of // an API call. - _SourceAPIResult + sourceAPIResult - // _SourceLocalFilter indicates the parameter is only used as input to the + // sourceLocalFilter indicates the parameter is only used as input to the // resource or data source and not to be entered into the state file. - _SourceLocalFilter + sourceLocalFilter ) const ( - // _ModifyState is a mask that selects all attribute sources that can modify + // modifyState is a mask that selects all attribute sources that can modify // the state (i.e. everything but filters used in data sources). - _ModifyState = _SourceUserRequired | _SourceUserOptional | _SourceAPIResult + modifyState = sourceUserRequired | sourceUserOptional | sourceAPIResult - // _ComputedAttrMask is a mask that selects _Source*'s that are Computed in the + // computedAttrMask is a mask that selects source*'s that are Computed in the // schema. - _ComputedAttrMask = _SourceAPIResult + computedAttrMask = sourceAPIResult - // _OptionalAttrMask is a mask that selects _Source*'s that are Optional in the + // optionalAttrMask is a mask that selects source*'s that are Optional in the // schema. - _OptionalAttrMask = _SourceAPIResult | _SourceLocalFilter + optionalAttrMask = sourceAPIResult | sourceLocalFilter - // _RequiredAttrMask is a mask that selects _Source*'s that are Required in the + // requiredAttrMask is a mask that selects source*'s that are Required in the // schema. - _RequiredAttrMask = _SourceUserRequired + requiredAttrMask = sourceUserRequired ) -type _TypeEntry struct { - APIName _APIAttr - APIAliases []_APIAttr - Source _SourceFlags +type typeEntry struct { + APIName apiAttr + APIAliases []apiAttr + Source sourceFlags Default interface{} Description string - SchemaName _SchemaAttr + SchemaName schemaAttr Type schema.ValueType ValidateFuncs []interface{} - SetMembers map[_TypeKey]*_TypeEntry - ListSchema map[_TypeKey]*_TypeEntry + SetMembers map[typeKey]*typeEntry + ListSchema map[typeKey]*typeEntry // APITest, if returns true, will call APIToState. The if the value was // found, the second return parameter will include the value that should be // set in the state store. - APITest func(*_TypeEntry, interface{}) (interface{}, bool) + APITest func(*typeEntry, interface{}) (interface{}, bool) - // APIToState takes the value from APITest and writes it to the _AttrWriter - APIToState func(*_TypeEntry, interface{}, _AttrWriter) error + // APIToState takes the value from APITest and writes it to the attrWriter + APIToState func(*typeEntry, interface{}, attrWriter) error // ConfigRead, if it returns true, returned a value that will be passed to its // ConfigUse handler. - ConfigRead func(*_TypeEntry, _AttrReader) (interface{}, bool) + ConfigRead func(*typeEntry, attrReader) (interface{}, bool) // ConfigUse takes the value returned from ConfigRead as the second argument // and a 3rd optional opaque context argument. - ConfigUse func(e *_TypeEntry, v interface{}, target interface{}) error + ConfigUse func(e *typeEntry, v interface{}, target interface{}) error } -type _TypeHandlers struct { - APITest func(*_TypeEntry, interface{}) (interface{}, bool) - APIToState func(*_TypeEntry, interface{}, _AttrWriter) error +type typeHandlers struct { + APITest func(*typeEntry, interface{}) (interface{}, bool) + APIToState func(*typeEntry, interface{}, attrWriter) error } -var _TypeHandlerLookupMap = map[schema.ValueType]*_TypeHandlers{ - schema.TypeBool: &_TypeHandlers{ - APITest: _APITestBool, - APIToState: _APIToStateBool, +var typeHandlerLookupMap = map[schema.ValueType]*typeHandlers{ + schema.TypeBool: &typeHandlers{ + APITest: apiTestBool, + APIToState: apiToStateBool, }, - schema.TypeFloat: &_TypeHandlers{ - APITest: _APITestFloat64, - APIToState: _APIToStateFloat64, + schema.TypeFloat: &typeHandlers{ + APITest: apiTestFloat64, + APIToState: apiToStateFloat64, }, - schema.TypeList: &_TypeHandlers{ - APITest: _APITestList, - APIToState: _APIToStateList, + schema.TypeList: &typeHandlers{ + APITest: apiTestList, + APIToState: apiToStateList, }, - schema.TypeMap: &_TypeHandlers{ - APITest: _APITestMap, - APIToState: _APIToStateMap, + schema.TypeMap: &typeHandlers{ + APITest: apiTestMap, + APIToState: apiToStateMap, }, - schema.TypeSet: &_TypeHandlers{ - APITest: _APITestSet, - APIToState: _APIToStateSet, + schema.TypeSet: &typeHandlers{ + APITest: apiTestSet, + APIToState: apiToStateSet, }, - schema.TypeString: &_TypeHandlers{ - APITest: _APITestString, - APIToState: _APIToStateString, + schema.TypeString: &typeHandlers{ + APITest: apiTestString, + APIToState: apiToStateString, }, } -func _APITestBool(e *_TypeEntry, self interface{}) (interface{}, bool) { +func apiTestBool(e *typeEntry, self interface{}) (interface{}, bool) { m := self.(map[string]interface{}) v, found := m[string(e.APIName)] @@ -153,7 +153,7 @@ func _APITestBool(e *_TypeEntry, self interface{}) (interface{}, bool) { return false, false } -func _APITestFloat64(e *_TypeEntry, self interface{}) (interface{}, bool) { +func apiTestFloat64(e *typeEntry, self interface{}) (interface{}, bool) { m := self.(map[string]interface{}) v, found := m[string(e.APIName)] @@ -167,20 +167,20 @@ func _APITestFloat64(e *_TypeEntry, self interface{}) (interface{}, bool) { return 0.0, false } -func _APITestID(e *_TypeEntry, self interface{}) (interface{}, bool) { +func apiTestID(e *typeEntry, self interface{}) (interface{}, bool) { m := self.(map[string]interface{}) - v, _ := _APITestString(e, m) + v, _ := apiTestString(e, m) // Unconditionally return true so that the call to the APIToState handler can // return an error. return v, true } -func _APITestList(e *_TypeEntry, self interface{}) (interface{}, bool) { +func apiTestList(e *typeEntry, self interface{}) (interface{}, bool) { m := self.(map[string]interface{}) - names := append([]_APIAttr{e.APIName}, e.APIAliases...) + names := append([]apiAttr{e.APIName}, e.APIAliases...) const defaultListLen = 8 l := make([]interface{}, 0, defaultListLen) @@ -209,7 +209,7 @@ func _APITestList(e *_TypeEntry, self interface{}) (interface{}, bool) { return []interface{}{}, false } -func _APITestMap(e *_TypeEntry, selfRaw interface{}) (interface{}, bool) { +func apiTestMap(e *typeEntry, selfRaw interface{}) (interface{}, bool) { self := selfRaw.(map[string]interface{}) v, found := self[string(e.APIName)] @@ -223,7 +223,7 @@ func _APITestMap(e *_TypeEntry, selfRaw interface{}) (interface{}, bool) { return "", false } -func _APITestSet(e *_TypeEntry, selfRaw interface{}) (interface{}, bool) { +func apiTestSet(e *typeEntry, selfRaw interface{}) (interface{}, bool) { self := selfRaw.(map[string]interface{}) v, found := self[string(e.APIName)] @@ -237,7 +237,7 @@ func _APITestSet(e *_TypeEntry, selfRaw interface{}) (interface{}, bool) { return "", false } -func _APITestString(e *_TypeEntry, selfRaw interface{}) (interface{}, bool) { +func apiTestString(e *typeEntry, selfRaw interface{}) (interface{}, bool) { self := selfRaw.(map[string]interface{}) v, found := self[string(e.APIName)] @@ -251,19 +251,19 @@ func _APITestString(e *_TypeEntry, selfRaw interface{}) (interface{}, bool) { return "", false } -func _APIToStateBool(e *_TypeEntry, v interface{}, w _AttrWriter) error { +func apiToStateBool(e *typeEntry, v interface{}, w attrWriter) error { return w.SetBool(e.SchemaName, v.(bool)) } -func _APIToStateID(e *_TypeEntry, v interface{}, w _AttrWriter) error { +func apiToStateID(e *typeEntry, v interface{}, w attrWriter) error { s, ok := v.(string) if !ok || len(s) == 0 { return fmt.Errorf("Unable to set %q's ID to an empty or non-string value: %#v", e.SchemaName, v) } - stateWriter, ok := w.(*_AttrWriterState) + stateWriter, ok := w.(*attrWriterState) if !ok { - return fmt.Errorf("PROVIDER BUG: unable to SetID with a non-_AttrWriterState") + return fmt.Errorf("PROVIDER BUG: unable to SetID with a non-attrWriterState") } stateWriter.SetID(s) @@ -271,7 +271,7 @@ func _APIToStateID(e *_TypeEntry, v interface{}, w _AttrWriter) error { return nil } -func _APIToStateFloat64(e *_TypeEntry, v interface{}, w _AttrWriter) error { +func apiToStateFloat64(e *typeEntry, v interface{}, w attrWriter) error { f, ok := v.(float64) if !ok { return fmt.Errorf("PROVIDER BUG: unable to cast %s to a float64", e.SchemaName) @@ -280,7 +280,7 @@ func _APIToStateFloat64(e *_TypeEntry, v interface{}, w _AttrWriter) error { return w.SetFloat64(e.SchemaName, f) } -func _APIToStateList(e *_TypeEntry, v interface{}, w _AttrWriter) error { +func apiToStateList(e *typeEntry, v interface{}, w attrWriter) error { l, ok := v.([]interface{}) if !ok { return fmt.Errorf("PROVIDER BUG: unable to cast %s to a list", e.SchemaName) @@ -289,20 +289,20 @@ func _APIToStateList(e *_TypeEntry, v interface{}, w _AttrWriter) error { return w.SetList(e.SchemaName, l) } -func _APIToStateMap(e *_TypeEntry, v interface{}, w _AttrWriter) error { +func apiToStateMap(e *typeEntry, v interface{}, w attrWriter) error { rawMap, ok := v.(map[string]interface{}) if !ok { return fmt.Errorf("PROVIDER BUG: unable to cast %s to a map", e.SchemaName) } - mWriter := _NewMapWriter(make(map[string]interface{}, len(rawMap))) + mWriter := newMapWriter(make(map[string]interface{}, len(rawMap))) // Make a lookup map by API Schema Name var setMembersLen int if e.SetMembers != nil { setMembersLen = len(e.SetMembers) } - apiLookup := make(map[string]*_TypeEntry, setMembersLen) + apiLookup := make(map[string]*typeEntry, setMembersLen) for _, typeEntry := range e.SetMembers { apiLookup[string(e.SchemaName)] = typeEntry } @@ -317,7 +317,7 @@ func _APIToStateMap(e *_TypeEntry, v interface{}, w _AttrWriter) error { } if !usedSchemaHandler { - if err := mWriter.Set(_SchemaAttr(k), v); err != nil { + if err := mWriter.Set(schemaAttr(k), v); err != nil { return errwrap.Wrapf("Unable to store map in state: {{err}}", err) } } @@ -326,7 +326,7 @@ func _APIToStateMap(e *_TypeEntry, v interface{}, w _AttrWriter) error { return w.SetMap(e.SchemaName, mWriter.ToMap()) } -func _APIToStateSet(e *_TypeEntry, v interface{}, w _AttrWriter) error { +func apiToStateSet(e *typeEntry, v interface{}, w attrWriter) error { s, ok := v.([]map[string]interface{}) if !ok { return fmt.Errorf("PROVIDER BUG: unable to cast %s to a set", e.SchemaName) @@ -338,7 +338,7 @@ func _APIToStateSet(e *_TypeEntry, v interface{}, w _AttrWriter) error { return w.SetSet(e.SchemaName, set) } -func _APIToStateString(e *_TypeEntry, v interface{}, w _AttrWriter) error { +func apiToStateString(e *typeEntry, v interface{}, w attrWriter) error { s, ok := v.(string) if !ok { return fmt.Errorf("PROVIDER BUG: unable to cast %s to a float64", e.SchemaName) @@ -347,7 +347,7 @@ func _APIToStateString(e *_TypeEntry, v interface{}, w _AttrWriter) error { return w.SetString(e.SchemaName, s) } -func _HashMap(in interface{}) int { +func hashMap(in interface{}) int { return 0 m, ok := in.(map[string]interface{}) if !ok { @@ -362,8 +362,8 @@ func _HashMap(in interface{}) int { sort.Strings(keys) b := &bytes.Buffer{} - const _DefaultHashBufSize = 4096 - b.Grow(_DefaultHashBufSize) + const defaultHashBufSize = 4096 + b.Grow(defaultHashBufSize) for _, k := range keys { v, found := m[k] @@ -390,7 +390,7 @@ func _HashMap(in interface{}) int { return hashcode.String(b.String()) } -func _Indirect(v interface{}) interface{} { +func indirect(v interface{}) interface{} { switch v.(type) { case string: return v @@ -405,8 +405,8 @@ func _Indirect(v interface{}) interface{} { } } -func (e *_TypeEntry) LookupDefaultTypeHandler() *_TypeHandlers { - h, found := _TypeHandlerLookupMap[e.Type] +func (e *typeEntry) LookupDefaultTypeHandler() *typeHandlers { + h, found := typeHandlerLookupMap[e.Type] if !found { panic(fmt.Sprintf("PROVIDER BUG: unable to lookup %q's type (%#v)", e.SchemaName, e.Type)) } @@ -414,8 +414,8 @@ func (e *_TypeEntry) LookupDefaultTypeHandler() *_TypeHandlers { return h } -func (e *_TypeEntry) MustLookupTypeHandler() *_TypeHandlers { - h := &_TypeHandlers{ +func (e *typeEntry) MustLookupTypeHandler() *typeHandlers { + h := &typeHandlers{ APITest: e.APITest, APIToState: e.APIToState, } @@ -441,10 +441,10 @@ func (e *_TypeEntry) MustLookupTypeHandler() *_TypeHandlers { return h } -// _NegateBoolToState is a factory function that creates a new function that +// negateBoolToState is a factory function that creates a new function that // negates whatever the bool is that's passed in as an argument. -func _NegateBoolToState(fn func(*_TypeEntry, interface{}, _AttrWriter) error) func(*_TypeEntry, interface{}, _AttrWriter) error { - return func(e *_TypeEntry, v interface{}, w _AttrWriter) error { +func negateBoolToState(fn func(*typeEntry, interface{}, attrWriter) error) func(*typeEntry, interface{}, attrWriter) error { + return func(e *typeEntry, v interface{}, w attrWriter) error { b, ok := v.(bool) if !ok { return fmt.Errorf("Unable to type assert non-bool value: %#v", v) @@ -454,29 +454,29 @@ func _NegateBoolToState(fn func(*_TypeEntry, interface{}, _AttrWriter) error) fu } } -// _StateSet sets an attribute based on an attrName. Return an error if the +// stateSet sets an attribute based on an attrName. Return an error if the // Set() to schema.ResourceData fails. -func _StateSet(d *schema.ResourceData, attrName _SchemaAttr, v interface{}) error { - if err := d.Set(string(attrName), _Indirect(v)); err != nil { +func stateSet(d *schema.ResourceData, attrName schemaAttr, v interface{}) error { + if err := d.Set(string(attrName), indirect(v)); err != nil { return fmt.Errorf("PROVIDER BUG: failed set schema attribute %s to value %#v: %v", attrName, v, err) } return nil } -func _TypeEntryListToSchema(e *_TypeEntry) map[string]*schema.Schema { +func typeEntryListToSchema(e *typeEntry) map[string]*schema.Schema { return map[string]*schema.Schema{ string(e.SchemaName): e.ToSchema(), } } -func _TypeEntryMapToResource(in map[_TypeKey]*_TypeEntry) *schema.Resource { +func typeEntryMapToResource(in map[typeKey]*typeEntry) *schema.Resource { return &schema.Resource{ - Schema: _TypeEntryMapToSchema(in), + Schema: typeEntryMapToSchema(in), } } -func _TypeEntryMapToSchema(in map[_TypeKey]*_TypeEntry) map[string]*schema.Schema { +func typeEntryMapToSchema(in map[typeKey]*typeEntry) map[string]*schema.Schema { out := make(map[string]*schema.Schema, len(in)) for _, e := range in { out[string(e.SchemaName)] = e.ToSchema() @@ -485,12 +485,12 @@ func _TypeEntryMapToSchema(in map[_TypeKey]*_TypeEntry) map[string]*schema.Schem return out } -func (e *_TypeEntry) Validate() { - if e.Source&_SourceAPIResult != 0 && e.Type == schema.TypeSet { +func (e *typeEntry) Validate() { + if e.Source&sourceAPIResult != 0 && e.Type == schema.TypeSet { panic(fmt.Sprintf("PROVIDER BUG: %s can not be computed and of type Set", e.SchemaName)) } - if e.Source&_SourceLocalFilter != 0 { + if e.Source&sourceLocalFilter != 0 { if e.ConfigRead == nil { panic(fmt.Sprintf("PROVIDER BUG: %s can not be configured as a local filter and be missing a config read handler", e.SchemaName)) } @@ -504,15 +504,15 @@ func (e *_TypeEntry) Validate() { panic(fmt.Sprintf("PROVIDER BUG: %s is not of type Set but has SetMembers set", e.SchemaName)) } - if e.Source&(_SourceUserRequired|_SourceAPIResult) == (_SourceUserRequired | _SourceAPIResult) { - panic(fmt.Sprintf("PROVIDER BUG: %#v and %#v are mutually exclusive Source flags", _SourceUserRequired, _SourceAPIResult)) + if e.Source&(sourceUserRequired|sourceAPIResult) == (sourceUserRequired | sourceAPIResult) { + panic(fmt.Sprintf("PROVIDER BUG: %#v and %#v are mutually exclusive Source flags", sourceUserRequired, sourceAPIResult)) } } // MakeValidateionFunc takes a list of typed validator inputs from the receiver // and creates a validation closure that calls each validator in serial until // either a warning or error is returned from the first validation function. -func (e *_TypeEntry) MakeValidationFunc() func(v interface{}, key string) (warnings []string, errors []error) { +func (e *typeEntry) MakeValidationFunc() func(v interface{}, key string) (warnings []string, errors []error) { if len(e.ValidateFuncs) == 0 { return nil } @@ -520,12 +520,12 @@ func (e *_TypeEntry) MakeValidationFunc() func(v interface{}, key string) (warni fns := make([]func(v interface{}, key string) (warnings []string, errors []error), 0, len(e.ValidateFuncs)) for _, v := range e.ValidateFuncs { switch u := v.(type) { - case _ValidateDurationMin: - fns = append(fns, _ValidateDurationMinFactory(e, string(u))) - case _ValidateIntMin: - fns = append(fns, _ValidateIntMinFactory(e, int(u))) - case _ValidateRegexp: - fns = append(fns, _ValidateRegexpFactory(e, string(u))) + case validateDurationMin: + fns = append(fns, validateDurationMinFactory(e, string(u))) + case validateIntMin: + fns = append(fns, validateIntMinFactory(e, int(u))) + case validateRegexp: + fns = append(fns, validateRegexpFactory(e, string(u))) } } @@ -540,15 +540,15 @@ func (e *_TypeEntry) MakeValidationFunc() func(v interface{}, key string) (warni } } -func (e *_TypeEntry) ToSchema() *schema.Schema { +func (e *typeEntry) ToSchema() *schema.Schema { e.Validate() attr := &schema.Schema{ - Computed: e.Source&_ComputedAttrMask != 0, + Computed: e.Source&computedAttrMask != 0, Default: e.Default, Description: e.Description, - Optional: e.Source&_OptionalAttrMask != 0, - Required: e.Source&_RequiredAttrMask != 0, + Optional: e.Source&optionalAttrMask != 0, + Required: e.Source&requiredAttrMask != 0, Type: e.Type, ValidateFunc: e.MakeValidationFunc(), } @@ -561,19 +561,19 @@ func (e *_TypeEntry) ToSchema() *schema.Schema { Type: schema.TypeString, } } else { - attr.Elem = _TypeEntryMapToResource(e.ListSchema) + attr.Elem = typeEntryMapToResource(e.ListSchema) } case schema.TypeSet: attr.Elem = &schema.Resource{ - Schema: _TypeEntryMapToSchema(e.SetMembers), + Schema: typeEntryMapToSchema(e.SetMembers), } } return attr } -func _MapStringToMapInterface(in map[string]string) map[string]interface{} { +func mapStringToMapInterface(in map[string]string) map[string]interface{} { out := make(map[string]interface{}, len(in)) for k, v := range in { out[k] = v @@ -581,7 +581,7 @@ func _MapStringToMapInterface(in map[string]string) map[string]interface{} { return out } -func _ValidateDurationMinFactory(e *_TypeEntry, minDuration string) func(v interface{}, key string) (warnings []string, errors []error) { +func validateDurationMinFactory(e *typeEntry, minDuration string) func(v interface{}, key string) (warnings []string, errors []error) { dMin, err := time.ParseDuration(minDuration) if err != nil { panic(fmt.Sprintf("PROVIDER BUG: duration %q not valid: %#v", minDuration, err)) @@ -601,7 +601,7 @@ func _ValidateDurationMinFactory(e *_TypeEntry, minDuration string) func(v inter } } -func _ValidateIntMinFactory(e *_TypeEntry, min int) func(v interface{}, key string) (warnings []string, errors []error) { +func validateIntMinFactory(e *typeEntry, min int) func(v interface{}, key string) (warnings []string, errors []error) { return func(v interface{}, key string) (warnings []string, errors []error) { if v.(int) < min { errors = append(errors, fmt.Errorf("Invalid %s specified: %d less than the required minimum %d", e.SchemaName, v.(int), min)) @@ -611,7 +611,7 @@ func _ValidateIntMinFactory(e *_TypeEntry, min int) func(v interface{}, key stri } } -func _ValidateRegexpFactory(e *_TypeEntry, reString string) func(v interface{}, key string) (warnings []string, errors []error) { +func validateRegexpFactory(e *typeEntry, reString string) func(v interface{}, key string) (warnings []string, errors []error) { re := regexp.MustCompile(reString) return func(v interface{}, key string) (warnings []string, errors []error) { From 14764455933274af8a94117b778291d1fa24cab4 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Fri, 10 Feb 2017 14:11:55 -0800 Subject: [PATCH 09/23] Update `consul_catalog_nodes` to conform to normal resource guidelines. --- .../data_source_consul_catalog_nodes.go | 482 ++++++------------ .../data_source_consul_catalog_nodes_test.go | 1 - builtin/providers/consul/utils.go | 102 +--- builtin/providers/consul/validators.go | 100 ++++ 4 files changed, 259 insertions(+), 426 deletions(-) create mode 100644 builtin/providers/consul/validators.go diff --git a/builtin/providers/consul/data_source_consul_catalog_nodes.go b/builtin/providers/consul/data_source_consul_catalog_nodes.go index a1d8d176b603..0565d21b1bf7 100644 --- a/builtin/providers/consul/data_source_consul_catalog_nodes.go +++ b/builtin/providers/consul/data_source_consul_catalog_nodes.go @@ -9,315 +9,113 @@ import ( "github.com/hashicorp/terraform/helper/schema" ) -// Top-level consul_catalog_nodes attributes const ( - catalogNodes typeKey = iota - catalogNodesAllowStale - catalogNodesDatacenter - catalogNodesNear - catalogNodesRequireConsistent - catalogNodesToken - catalogNodesWaitIndex - catalogNodesWaitTime + allowStale = "allow_stale" + nodeMeta = "node_meta" + nodesAttr = "nodes" + requireConsistent = "require_consistent" + token = "token" + waitIndex = "wait_index" + waitTime = "wait_time" + + nodeID = "id" + nodeAddress = "address" + nodeMetaAttr = "meta" + nodeName = "name" + nodeTaggedAddresses = "tagged_addresses" + + apiTaggedLAN = "lan" + apiTaggedWAN = "wan" + schemaTaggedLAN = "lan" + schemaTaggedWAN = "wan" ) -// node.* attributes -const ( - catalogNodeID typeKey = iota - catalogNodeName - catalogNodeAddress - catalogNodeTaggedAddresses - catalogNodeMeta -) - -// node.tagged_addresses.* attributes -const ( - catalogNodeTaggedAddressesLAN typeKey = iota - catalogNodeTaggedAddressesWAN -) - -var catalogNodeAttrs = map[typeKey]*typeEntry{ - catalogNodeID: { - APIName: "ID", - SchemaName: "id", - Source: sourceAPIResult, - Type: schema.TypeString, - ValidateFuncs: []interface{}{ - validateRegexp(`^[\S]+$`), - }, - APITest: func(e *typeEntry, v interface{}) (interface{}, bool) { - node := v.(*consulapi.Node) - - if id := node.ID; id != "" { - return id, true - } - - // Use the node name - confusingly stored in the Node attribute - if no ID - // is available. - if name := node.Node; name != "" { - return name, true - } - - return "", false - }, - }, - catalogNodeName: { - APIName: "Name", - SchemaName: "name", - Source: sourceAPIResult, - Type: schema.TypeString, - ValidateFuncs: []interface{}{ - validateRegexp(`^[\S]+$`), - }, - APITest: func(e *typeEntry, v interface{}) (interface{}, bool) { - node := v.(*consulapi.Node) - - if name := node.Node; name != "" { - return name, true - } - - return "", false - }, - }, - catalogNodeAddress: { - APIName: "Address", - SchemaName: "address", - Source: sourceAPIResult, - Type: schema.TypeString, - APITest: func(e *typeEntry, v interface{}) (interface{}, bool) { - node := v.(*consulapi.Node) - - if addr := node.Address; addr != "" { - return addr, true - } - - return "", false - }, - }, - catalogNodeTaggedAddresses: { - APIName: "TaggedAddresses", - SchemaName: "tagged_addresses", - Source: sourceAPIResult, - Type: schema.TypeMap, - SetMembers: map[typeKey]*typeEntry{ - catalogNodeTaggedAddressesLAN: { - APIName: "LAN", - SchemaName: "lan", - Source: sourceAPIResult, - Type: schema.TypeString, - APITest: func(e *typeEntry, v interface{}) (interface{}, bool) { - m := v.(map[string]string) - - if addr, found := m[string(e.SchemaName)]; found { - return addr, true - } - - return nil, false - }, +func dataSourceConsulCatalogNodes() *schema.Resource { + return &schema.Resource{ + Read: dataSourceConsulCatalogNodesRead, + Schema: map[string]*schema.Schema{ + allowStale: &schema.Schema{ + Optional: true, + Default: true, + Type: schema.TypeBool, }, - catalogNodeTaggedAddressesWAN: { - APIName: "WAN", - SchemaName: "wan", - Source: sourceAPIResult, - Type: schema.TypeString, - APITest: func(e *typeEntry, v interface{}) (interface{}, bool) { - m := v.(map[string]string) - - if addr, found := m[string(e.SchemaName)]; found { - return addr, true - } - - return nil, false + nodesAttr: &schema.Schema{ + Computed: true, + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + nodeID: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + ValidateFunc: makeValidationFunc(nodeID, []interface{}{validateRegexp(`^[\S]+$`)}), + }, + nodeName: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + ValidateFunc: makeValidationFunc(nodeName, []interface{}{validateRegexp(`^[\S]+$`)}), + }, + nodeAddress: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + nodeMetaAttr: &schema.Schema{ + Type: schema.TypeMap, + Computed: true, + }, + nodeTaggedAddresses: &schema.Schema{ + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + schemaTaggedLAN: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + schemaTaggedWAN: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, }, }, + requireConsistent: &schema.Schema{ + Optional: true, + Default: false, + Type: schema.TypeBool, + }, + token: &schema.Schema{ + Optional: true, + Default: true, + Type: schema.TypeString, + }, + waitIndex: &schema.Schema{ + Optional: true, + Default: true, + Type: schema.TypeInt, + ValidateFunc: makeValidationFunc(waitIndex, []interface{}{ + validateIntMin(0), + }), + }, + waitTime: &schema.Schema{ + Optional: true, + Default: true, + Type: schema.TypeString, + ValidateFunc: makeValidationFunc(waitTime, []interface{}{ + validateDurationMin("0ns"), + }), + }, }, - APITest: func(e *typeEntry, v interface{}) (interface{}, bool) { - node := v.(*consulapi.Node) - - if addrs := node.TaggedAddresses; len(addrs) > 0 { - return mapStringToMapInterface(addrs), true - } - - return nil, false - }, - }, - catalogNodeMeta: { - APIName: "Meta", - SchemaName: "meta", - Source: sourceAPIResult, - Type: schema.TypeMap, - APITest: func(e *typeEntry, v interface{}) (interface{}, bool) { - node := v.(*consulapi.Node) - - if meta := node.Meta; len(meta) > 0 { - return mapStringToMapInterface(meta), true - } - - return nil, false - }, - }, -} - -var catalogNodesAttrs = map[typeKey]*typeEntry{ - catalogNodesAllowStale: { - SchemaName: "allow_stale", - Source: sourceLocalFilter, - Type: schema.TypeBool, - Default: true, - ConfigRead: func(e *typeEntry, r attrReader) (interface{}, bool) { - b, ok := r.GetBoolOK(e.SchemaName) - if !ok { - return nil, false - } - - return b, true - }, - ConfigUse: func(e *typeEntry, v interface{}, target interface{}) error { - b := v.(bool) - queryOpts := target.(*consulapi.QueryOptions) - queryOpts.AllowStale = b - return nil - }, - }, - catalogNodesDatacenter: { - SchemaName: "datacenter", - Source: sourceLocalFilter, - Type: schema.TypeString, - ConfigRead: func(e *typeEntry, r attrReader) (interface{}, bool) { - s, ok := r.GetStringOK(e.SchemaName) - if !ok { - return nil, false - } - - return s, true - }, - ConfigUse: func(e *typeEntry, v interface{}, target interface{}) error { - s := v.(string) - queryOpts := target.(*consulapi.QueryOptions) - queryOpts.Datacenter = s - return nil - }, - }, - catalogNodesNear: { - SchemaName: "near", - Source: sourceLocalFilter, - Type: schema.TypeString, - ConfigRead: func(e *typeEntry, r attrReader) (interface{}, bool) { - s, ok := r.GetStringOK(e.SchemaName) - if !ok { - return nil, false - } - - return s, true - }, - ConfigUse: func(e *typeEntry, v interface{}, target interface{}) error { - s := v.(string) - queryOpts := target.(*consulapi.QueryOptions) - queryOpts.Near = s - return nil - }, - }, - catalogNodes: { - SchemaName: "nodes", - Source: sourceAPIResult, - Type: schema.TypeList, - ListSchema: catalogNodeAttrs, - }, - catalogNodesRequireConsistent: { - SchemaName: "require_consistent", - Source: sourceLocalFilter, - Type: schema.TypeBool, - Default: false, - ConfigRead: func(e *typeEntry, r attrReader) (interface{}, bool) { - b, ok := r.GetBoolOK(e.SchemaName) - if !ok { - return nil, false - } - - return b, true - }, - ConfigUse: func(e *typeEntry, v interface{}, target interface{}) error { - b := v.(bool) - queryOpts := target.(*consulapi.QueryOptions) - queryOpts.RequireConsistent = b - return nil - }, - }, - catalogNodesToken: { - SchemaName: "token", - Source: sourceLocalFilter, - Type: schema.TypeString, - ConfigRead: func(e *typeEntry, r attrReader) (interface{}, bool) { - s, ok := r.GetStringOK(e.SchemaName) - if !ok { - return nil, false - } - - return s, true - }, - ConfigUse: func(e *typeEntry, v interface{}, target interface{}) error { - s := v.(string) - queryOpts := target.(*consulapi.QueryOptions) - queryOpts.Token = s - return nil - }, - }, - catalogNodesWaitIndex: { - SchemaName: "wait_index", - Source: sourceLocalFilter, - Type: schema.TypeInt, - ValidateFuncs: []interface{}{ - validateIntMin(0), - }, - ConfigRead: func(e *typeEntry, r attrReader) (interface{}, bool) { - i, ok := r.GetIntOK(e.SchemaName) - if !ok { - return nil, false - } - - return uint64(i), true - }, - ConfigUse: func(e *typeEntry, v interface{}, target interface{}) error { - i := v.(uint64) - queryOpts := target.(*consulapi.QueryOptions) - queryOpts.WaitIndex = i - return nil - }, - }, - catalogNodesWaitTime: { - SchemaName: "wait_time", - Source: sourceLocalFilter, - Type: schema.TypeString, - ValidateFuncs: []interface{}{ - validateDurationMin("0ns"), - }, - ConfigRead: func(e *typeEntry, r attrReader) (interface{}, bool) { - d, ok := r.GetDurationOK(e.SchemaName) - if !ok { - return nil, false - } - - return d, true - }, - ConfigUse: func(e *typeEntry, v interface{}, target interface{}) error { - d := v.(time.Duration) - queryOpts := target.(*consulapi.QueryOptions) - queryOpts.WaitTime = d - return nil - }, - }, -} - -func dataSourceConsulCatalogNodes() *schema.Resource { - return &schema.Resource{ - Read: dataSourceConsulCatalogNodesRead, - Schema: typeEntryMapToSchema(catalogNodesAttrs), } } func dataSourceConsulCatalogNodesRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*consulapi.Client) + // Parse out data source filters to populate Consul's query options + dc, err := getDC(d, client) if err != nil { return err @@ -327,20 +125,34 @@ func dataSourceConsulCatalogNodesRead(d *schema.ResourceData, meta interface{}) Datacenter: dc, } - cfgReader := newConfigReader(d) + if v, ok := d.GetOk(allowStale); ok { + queryOpts.AllowStale = v.(bool) + } - // Construct the query options - for _, e := range catalogNodesAttrs[catalogNodes].ListSchema { - // Only evaluate attributes that impact the state - if e.Source&sourceLocalFilter == 0 { - continue - } + if v, ok := d.GetOk(requireConsistent); ok { + queryOpts.RequireConsistent = v.(bool) + } - if v, ok := e.ConfigRead(e, cfgReader); ok { - if err := e.ConfigUse(e, v, queryOpts); err != nil { - return errwrap.Wrapf(fmt.Sprintf("error writing %q's query option: {{err}}", e.SchemaName), err) - } + if v, ok := d.GetOk(nodeMeta); ok { + m := v.(map[string]interface{}) + nodeMetaMap := make(map[string]string, len(nodeMeta)) + for s, t := range m { + nodeMetaMap[s] = t.(string) } + queryOpts.NodeMeta = nodeMetaMap + } + + if v, ok := d.GetOk(token); ok { + queryOpts.Token = v.(string) + } + + if v, ok := d.GetOk(waitIndex); ok { + queryOpts.WaitIndex = uint64(v.(int)) + } + + if v, ok := d.GetOk(waitTime); ok { + d, _ := time.ParseDuration(v.(string)) + queryOpts.WaitTime = d } nodes, meta, err := client.Catalog().Nodes(queryOpts) @@ -348,41 +160,51 @@ func dataSourceConsulCatalogNodesRead(d *schema.ResourceData, meta interface{}) return err } - // TODO(sean@): It'd be nice if this data source had a way of filtering out - // irrelevant data so only the important bits are persisted in the state file. - // Something like an attribute mask or even a regexp of matching schema - // attributesknames would be sufficient in the most basic case. Food for - // thought. - l := make([]interface{}, 0, len(nodes)) for _, node := range nodes { - mWriter := newMapWriter(make(map[string]interface{}, len(catalogNodeAttrs))) + const defaultNodeAttrs = 4 + m := make(map[string]interface{}, defaultNodeAttrs) + id := node.ID + if id == "" { + id = node.Node + } - // /v1/catalog/nodes returns a list of node objects - for _, e := range catalogNodesAttrs[catalogNodes].ListSchema { - // Only evaluate attributes that impact the state - if e.Source&modifyState == 0 { - continue - } + m[nodeID] = id + m[nodeName] = node.Node + m[nodeAddress] = node.Address - h := e.MustLookupTypeHandler() + { + const initNumTaggedAddrs = 2 + taggedAddrs := make(map[string]interface{}, initNumTaggedAddrs) + if addr, found := node.TaggedAddresses[apiTaggedLAN]; found { + taggedAddrs[schemaTaggedLAN] = addr + } + if addr, found := node.TaggedAddresses[apiTaggedWAN]; found { + taggedAddrs[schemaTaggedWAN] = addr + } + m[nodeTaggedAddresses] = taggedAddrs + } - if v, ok := h.APITest(e, node); ok { - if err := h.APIToState(e, v, mWriter); err != nil { - return errwrap.Wrapf(fmt.Sprintf("error writing %q's data to state: {{err}}", e.SchemaName), err) - } + { + const initNumMetaAddrs = 4 + metaVals := make(map[string]interface{}, initNumMetaAddrs) + for s, t := range node.Meta { + metaVals[s] = t } + m[nodeMetaAttr] = metaVals } - l = append(l, mWriter.ToMap()) + l = append(l, m) } - dataSourceWriter := newStateWriter(d) - dataSourceWriter.SetList(catalogNodesAttrs[catalogNodes].SchemaName, l) - dataSourceWriter.SetString(catalogNodesAttrs[catalogNodesDatacenter].SchemaName, dc) const idKeyFmt = "catalog-nodes-%s" - dataSourceWriter.SetID(fmt.Sprintf(idKeyFmt, dc)) + d.SetId(fmt.Sprintf(idKeyFmt, dc)) + + d.Set("datacenter", dc) + if err := d.Set(nodesAttr, l); err != nil { + return errwrap.Wrapf("Unable to store nodes: {{err}}", err) + } return nil } diff --git a/builtin/providers/consul/data_source_consul_catalog_nodes_test.go b/builtin/providers/consul/data_source_consul_catalog_nodes_test.go index ede6f4342891..d4c46f2f4269 100644 --- a/builtin/providers/consul/data_source_consul_catalog_nodes_test.go +++ b/builtin/providers/consul/data_source_consul_catalog_nodes_test.go @@ -28,7 +28,6 @@ const testAccDataConsulCatalogNodesConfig = ` data "consul_catalog_nodes" "read" { allow_stale = true require_consistent = false - near = "_agent" token = "" wait_index = 0 wait_time = "1m" diff --git a/builtin/providers/consul/utils.go b/builtin/providers/consul/utils.go index d544c9850cc5..ce7c764c0654 100644 --- a/builtin/providers/consul/utils.go +++ b/builtin/providers/consul/utils.go @@ -3,10 +3,8 @@ package consul import ( "bytes" "fmt" - "regexp" "sort" "strconv" - "time" "github.com/hashicorp/errwrap" "github.com/hashicorp/terraform/helper/hashcode" @@ -28,19 +26,6 @@ type sourceFlags int // typeKey is the lookup mechanism for the generated schema. type typeKey int -// An array of inputs used as typed arguments and converted from their type into -// function objects that are dynamically constructed and executed. -type validatorInputs []interface{} - -// validateDurationMin is the minimum duration to accept as input -type validateDurationMin string - -// validateIntMin is the minimum integer value to accept as input -type validateIntMin int - -// validateRegexp is a regexp pattern to use to validate schema input. -type validateRegexp string - const ( // sourceUserRequired indicates the parameter must be provided by the user in // their configuration. @@ -509,48 +494,17 @@ func (e *typeEntry) Validate() { } } -// MakeValidateionFunc takes a list of typed validator inputs from the receiver -// and creates a validation closure that calls each validator in serial until -// either a warning or error is returned from the first validation function. -func (e *typeEntry) MakeValidationFunc() func(v interface{}, key string) (warnings []string, errors []error) { - if len(e.ValidateFuncs) == 0 { - return nil - } - - fns := make([]func(v interface{}, key string) (warnings []string, errors []error), 0, len(e.ValidateFuncs)) - for _, v := range e.ValidateFuncs { - switch u := v.(type) { - case validateDurationMin: - fns = append(fns, validateDurationMinFactory(e, string(u))) - case validateIntMin: - fns = append(fns, validateIntMinFactory(e, int(u))) - case validateRegexp: - fns = append(fns, validateRegexpFactory(e, string(u))) - } - } - - return func(v interface{}, key string) (warnings []string, errors []error) { - for _, fn := range fns { - warnings, errors = fn(v, key) - if len(warnings) > 0 || len(errors) > 0 { - break - } - } - return warnings, errors - } -} - func (e *typeEntry) ToSchema() *schema.Schema { e.Validate() attr := &schema.Schema{ - Computed: e.Source&computedAttrMask != 0, - Default: e.Default, - Description: e.Description, - Optional: e.Source&optionalAttrMask != 0, - Required: e.Source&requiredAttrMask != 0, - Type: e.Type, - ValidateFunc: e.MakeValidationFunc(), + Computed: e.Source&computedAttrMask != 0, + Default: e.Default, + Description: e.Description, + Optional: e.Source&optionalAttrMask != 0, + Required: e.Source&requiredAttrMask != 0, + Type: e.Type, + // ValidateFunc: e.MakeValidationFunc(), } // Fixup the type: use the real type vs a surrogate type @@ -580,45 +534,3 @@ func mapStringToMapInterface(in map[string]string) map[string]interface{} { } return out } - -func validateDurationMinFactory(e *typeEntry, minDuration string) func(v interface{}, key string) (warnings []string, errors []error) { - dMin, err := time.ParseDuration(minDuration) - if err != nil { - panic(fmt.Sprintf("PROVIDER BUG: duration %q not valid: %#v", minDuration, err)) - } - - return func(v interface{}, key string) (warnings []string, errors []error) { - d, err := time.ParseDuration(v.(string)) - if err != nil { - errors = append(errors, errwrap.Wrapf(fmt.Sprintf("Invalid %s specified (%q): {{err}}", e.SchemaName), err)) - } - - if d < dMin { - errors = append(errors, fmt.Errorf("Invalid %s specified: duration %q less than the required minimum %s", e.SchemaName, v.(string), dMin)) - } - - return warnings, errors - } -} - -func validateIntMinFactory(e *typeEntry, min int) func(v interface{}, key string) (warnings []string, errors []error) { - return func(v interface{}, key string) (warnings []string, errors []error) { - if v.(int) < min { - errors = append(errors, fmt.Errorf("Invalid %s specified: %d less than the required minimum %d", e.SchemaName, v.(int), min)) - } - - return warnings, errors - } -} - -func validateRegexpFactory(e *typeEntry, reString string) func(v interface{}, key string) (warnings []string, errors []error) { - re := regexp.MustCompile(reString) - - return func(v interface{}, key string) (warnings []string, errors []error) { - if !re.MatchString(v.(string)) { - errors = append(errors, fmt.Errorf("Invalid %s specified (%q): regexp failed to match string", e.SchemaName, v.(string))) - } - - return warnings, errors - } -} diff --git a/builtin/providers/consul/validators.go b/builtin/providers/consul/validators.go new file mode 100644 index 000000000000..55591cbaffb0 --- /dev/null +++ b/builtin/providers/consul/validators.go @@ -0,0 +1,100 @@ +package consul + +import ( + "fmt" + "regexp" + "time" + + "github.com/hashicorp/errwrap" +) + +// An array of inputs used as typed arguments and converted from their type into +// function objects that are dynamically constructed and executed. +type validatorInputs []interface{} + +// validateDurationMin is the minimum duration to accept as input +type validateDurationMin string + +// validateIntMin is the minimum integer value to accept as input +type validateIntMin int + +// validateRegexp is a regexp pattern to use to validate schema input. +type validateRegexp string + +// makeValidateionFunc takes the name of the attribute and a list of typed +// validator inputs in order to create a validation closure that calls each +// validator in serial until either a warning or error is returned from the +// first validation function. +func makeValidationFunc(name string, validators []interface{}) func(v interface{}, key string) (warnings []string, errors []error) { + if len(validators) == 0 { + return nil + } + + fns := make([]func(v interface{}, key string) (warnings []string, errors []error), 0, len(validators)) + for _, v := range validators { + switch u := v.(type) { + case validateDurationMin: + fns = append(fns, validateDurationMinFactory(name, string(u))) + case validateIntMin: + fns = append(fns, validateIntMinFactory(name, int(u))) + case validateRegexp: + fns = append(fns, validateRegexpFactory(name, string(u))) + } + } + + return func(v interface{}, key string) (warnings []string, errors []error) { + for _, fn := range fns { + warnings, errors = fn(v, key) + if len(warnings) > 0 || len(errors) > 0 { + break + } + } + return warnings, errors + } +} + +func validateDurationMinFactory(name, minDuration string) func(v interface{}, key string) (warnings []string, errors []error) { + dMin, err := time.ParseDuration(minDuration) + if err != nil { + return func(interface{}, string) (warnings []string, errors []error) { + return nil, []error{ + errwrap.Wrapf(fmt.Sprintf("PROVIDER BUG: duration %q not valid: {{err}}", minDuration), err), + } + } + } + + return func(v interface{}, key string) (warnings []string, errors []error) { + d, err := time.ParseDuration(v.(string)) + if err != nil { + errors = append(errors, errwrap.Wrapf(fmt.Sprintf("Invalid %s specified (%q): {{err}}", name), err)) + } + + if d < dMin { + errors = append(errors, fmt.Errorf("Invalid %s specified: duration %q less than the required minimum %s", name, v.(string), dMin)) + } + + return warnings, errors + } +} + +func validateIntMinFactory(name string, min int) func(v interface{}, key string) (warnings []string, errors []error) { + return func(v interface{}, key string) (warnings []string, errors []error) { + if v.(int) < min { + errors = append(errors, fmt.Errorf("Invalid %s specified: %d less than the required minimum %d", name, v.(int), min)) + } + + return warnings, errors + } +} + +func validateRegexpFactory(name string, reString string) func(v interface{}, key string) (warnings []string, errors []error) { + re := regexp.MustCompile(reString) + + return func(v interface{}, key string) (warnings []string, errors []error) { + if !re.MatchString(v.(string)) { + errors = append(errors, fmt.Errorf("Invalid %s specified (%q): regexp failed to match string", name, v.(string))) + } + + return warnings, errors + } +} From efb76b33747ba84800cf3e2ed686c9cc015f9f2b Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Mon, 13 Feb 2017 12:09:29 -0800 Subject: [PATCH 10/23] Update the style of the `consul_catalog_nodes` data source. --- .../consul/data_source_consul_agent_self.go | 2189 +++++++++++------ .../data_source_consul_agent_self_test.go | 60 +- .../data_source_consul_catalog_nodes.go | 44 +- builtin/providers/consul/utils.go | 537 +--- builtin/providers/consul/validators.go | 50 +- 5 files changed, 1509 insertions(+), 1371 deletions(-) diff --git a/builtin/providers/consul/data_source_consul_agent_self.go b/builtin/providers/consul/data_source_consul_agent_self.go index 98489267f07b..715013cfb949 100644 --- a/builtin/providers/consul/data_source_consul_agent_self.go +++ b/builtin/providers/consul/data_source_consul_agent_self.go @@ -2,6 +2,8 @@ package consul import ( "fmt" + "strconv" + "time" consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/errwrap" @@ -9,819 +11,811 @@ import ( ) const ( - agentSelfACLDatacenter typeKey = iota - agentSelfACLDefaultPolicy - agentSelfACLDisableTTL - agentSelfACLDownPolicy - agentSelfACLEnforceVersion8 - agentSelfACLTTL - agentSelfAddresses - agentSelfAdvertiseAddr - agentSelfAdvertiseAddrWAN - agentSelfAdvertiseAddrs - agentSelfAtlasJoin - agentSelfBindAddr - agentSelfBootstrap - agentSelfBootstrapExpect - agentSelfCAFile - agentSelfCertFile - agentSelfCheckDeregisterIntervalMin - agentSelfCheckDisableAnonymousSignature - agentSelfCheckDisableRemoteExec - agentSelfCheckReapInterval - agentSelfCheckUpdateInterval - agentSelfClientAddr - agentSelfDNSConfig - agentSelfDNSRecursors - agentSelfDataDir - agentSelfDatacenter - agentSelfDevMode - agentSelfDisableCoordinates - agentSelfDisableUpdateCheck - agentSelfDomain - agentSelfEnableDebug - agentSelfEnableSyslog - agentSelfEnableUI - agentSelfID - agentSelfKeyFile - agentSelfLeaveOnInt - agentSelfLeaveOnTerm - agentSelfLogLevel - agentSelfName - agentSelfPerformance - agentSelfPidFile - agentSelfPorts - agentSelfProtocol - agentSelfReconnectTimeoutLAN - agentSelfReconnectTimeoutWAN - agentSelfRejoinAfterLeave - agentSelfRetryJoin - agentSelfRetryJoinEC2 - agentSelfRetryJoinGCE - agentSelfRetryJoinWAN - agentSelfRetryMaxAttempts - agentSelfRetryMaxAttemptsWAN - agentSelfRevision - agentSelfSerfLANBindAddr - agentSelfSerfWANBindAddr - agentSelfServer - agentSelfServerName - agentSelfSessionTTLMin - agentSelfStartJoin - agentSelfStartJoinWAN - agentSelfSyslogFacility - agentSelfTLSMinVersion - agentSelfTaggedAddresses - agentSelfTelemetry - agentSelfTranslateWANAddrs - agentSelfUIDir - agentSelfUnixSockets - agentSelfVerifyIncoming - agentSelfVerifyOutgoing - agentSelfVerifyServerHostname - agentSelfVersion - agentSelfVersionPrerelease + agentSelfACLDatacenter = "acl_datacenter" + agentSelfACLDefaultPolicy = "acl_default_policy" + agentSelfACLDisabledTTL = "acl_disabled_ttl" + agentSelfACLDownPolicy = "acl_down_policy" + agentSelfACLEnforceVersion8 = "acl_enforce_0_8_semantics" + agentSelfACLTTL = "acl_ttl" + agentSelfAddresses = "addresses" + agentSelfAdvertiseAddr = "advertise_addr" + agentSelfAdvertiseAddrWAN = "wan" + agentSelfAdvertiseAddrs = "advertise_addrs" + agentSelfAtlasJoin = "atlas_join" + agentSelfBindAddr = "bind_addr" + agentSelfBootstrapExpect = "bootstrap_expect" + agentSelfBootstrapMode = "bootstrap_mode" + agentSelfCheckDeregisterIntervalMin = "check_deregister_interval_min" + agentSelfCheckReapInterval = "check_reap_interval" + agentSelfCheckUpdateInterval = "check_update_interval" + agentSelfClientAddr = "client_addr" + agentSelfDNSConfig = "dns" + agentSelfDNSRecursors = "dns_recursors" + agentSelfDataDir = "data_dir" + agentSelfDatacenter = "datacenter" + agentSelfDevMode = "dev_mode" + agentSelfDomain = "domain" + agentSelfEnableAnonymousSignature = "enable_anonymous_signature" + agentSelfEnableCoordinates = "enable_coordinates" + agentSelfEnableDebug = "enable_debug" + agentSelfEnableRemoteExec = "enable_remote_exec" + agentSelfEnableSyslog = "enable_syslog" + agentSelfEnableUI = "enable_ui" + agentSelfEnableUpdateCheck = "enable_update_check" + agentSelfID = "id" + agentSelfLeaveOnInt = "leave_on_int" + agentSelfLeaveOnTerm = "leave_on_term" + agentSelfLogLevel = "log_level" + agentSelfName = "name" + agentSelfPerformance = "performance" + agentSelfPidFile = "pid_file" + agentSelfPorts = "ports" + agentSelfProtocol = "protocol_version" + agentSelfReconnectTimeoutLAN = "reconnect_timeout_lan" + agentSelfReconnectTimeoutWAN = "reconnect_timeout_wan" + agentSelfRejoinAfterLeave = "rejoin_after_leave" + agentSelfRetryJoin = "retry_join" + agentSelfRetryJoinEC2 = "retry_join_ec2" + agentSelfRetryJoinWAN = "retry_join_wan" + agentSelfRetryMaxAttempts = "retry_max_attempts" + agentSelfRetryMaxAttemptsWAN = "retry_max_attempts_wan" + agentSelfSerfLANBindAddr = "serf_lan_bind_addr" + agentSelfSerfWANBindAddr = "serf_wan_bind_addr" + agentSelfServerMode = "server_mode" + agentSelfServerName = "server_name" + agentSelfSessionTTLMin = "session_ttl_min" + agentSelfStartJoin = "start_join" + agentSelfStartJoinWAN = "start_join_wan" + agentSelfSyslogFacility = "syslog_facility" + agentSelfTLSCAFile = "tls_ca_file" + agentSelfTLSCertFile = "tls_cert_file" + agentSelfTLSKeyFile = "tls_key_file" + agentSelfTLSMinVersion = "tls_min_version" + agentSelfTLSVerifyIncoming = "tls_verify_incoming" + agentSelfTLSVerifyOutgoing = "tls_verify_outgoing" + agentSelfTLSVerifyServerHostname = "tls_verify_server_hostname" + agentSelfTaggedAddresses = "tagged_addresses" + agentSelfTelemetry = "telemetry" + agentSelfTranslateWANAddrs = "translate_wan_addrs" + agentSelfUIDir = "ui_dir" + agentSelfUnixSockets = "unix_sockets" + agentSelfVersion = "version" + agentSelfVersionPrerelease = "version_prerelease" + agentSelfVersionRevision = "version_revision" ) const ( - agentSelfDNSAllowStale typeKey = iota - agentSelfDNSMaxStale - agentSelfRecursorTimeout - agentSelfDNSDisableCompression - agentSelfDNSEnableTruncate - agentSelfDNSNodeTTL - agentSelfDNSOnlyPassing - agentSelfDNSUDPAnswerLimit - agentSelfServiceTTL + agentSelfRetryJoinAWSAccessKeyID = "access_key_id" + agentSelfRetryJoinAWSRegion = "region" + agentSelfRetryJoinAWSSecretAccessKey = "secret_access_key" + agentSelfRetryJoinAWSTagKey = "tag_key" + agentSelfRetryJoinAWSTagValue = "tag_value" ) const ( - agentSelfPerformanceRaftMultiplier typeKey = iota + agentSelfRetryJoinGCE = "retry_join_gce" + agentSelfRetryJoinGCECredentialsFile = "credentials_file" + agentSelfRetryJoinGCEProjectName = "project_name" + agentSelfRetryJoinGCETagValue = "tag_value" + agentSelfRetryJoinGCEZonePattern = "zone_pattern" ) const ( - agentSelfPortsDNS typeKey = iota - agentSelfPortsHTTP - agentSelfPortsHTTPS - agentSelfPortsRPC - agentSelfPortsSerfLAN - agentSelfPortsSerfWAN - agentSelfPortsServer + agentSelfDNSAllowStale = "allow_stale" + agentSelfDNSEnableCompression = "enable_compression" + agentSelfDNSEnableTruncate = "enable_truncate" + agentSelfDNSMaxStale = "max_stale" + agentSelfDNSNodeTTL = "node_ttl" + agentSelfDNSOnlyPassing = "only_passing" + agentSelfDNSRecursorTimeout = "recursor_timeout" + agentSelfDNSServiceTTL = "service_ttl" + agentSelfDNSUDPAnswerLimit = "udp_answer_limit" ) const ( - agentSelfTaggedAddressesLAN typeKey = iota - agentSelfTaggedAddressesWAN + agentSelfPerformanceRaftMultiplier = "raft_multiplier" ) const ( - agentSelfTelemetryCirconusAPIApp typeKey = iota - agentSelfTelemetryCirconusAPIURL - agentSelfTelemetryCirconusBrokerID - agentSelfTelemetryCirconusBrokerSelectTag - agentSelfTelemetryCirconusCheckDisplayName - agentSelfTelemetryCirconusCheckForceMetricActiation - agentSelfTelemetryCirconusCheckID - agentSelfTelemetryCirconusCheckInstanceID - agentSelfTelemetryCirconusCheckSearchTag - agentSelfTelemetryCirconusCheckSubmissionURL - agentSelfTelemetryCirconusCheckTags - agentSelfTelemetryCirconusSubmissionInterval - agentSelfTelemetryDisableHostname - agentSelfTelemetryDogStatsdAddr - agentSelfTelemetryDogStatsdTags - agentSelfTelemetryStatsdAddr - agentSelfTelemetryStatsiteAddr - agentSelfTelemetryStatsitePrefix + agentSelfAPIPortsDNS = "dns" + agentSelfAPIPortsHTTP = "http" + agentSelfAPIPortsHTTPS = "https" + agentSelfAPIPortsRPC = "rpc" + agentSelfAPIPortsSerfLAN = "serf_lan" + agentSelfAPIPortsSerfWAN = "serf_wan" + agentSelfAPIPortsServer = "server" + + agentSelfSchemaPortsDNS = "dns" + agentSelfSchemaPortsHTTP = "http" + agentSelfSchemaPortsHTTPS = "https" + agentSelfSchemaPortsRPC = "rpc" + agentSelfSchemaPortsSerfLAN = "serf_lan" + agentSelfSchemaPortsSerfWAN = "serf_wan" + agentSelfSchemaPortsServer = "server" +) + +const ( + agentSelfTaggedAddressesLAN = "lan" + agentSelfTaggedAddressesWAN = "wan" +) + +const ( + agentSelfTelemetryCirconusAPIApp = "circonus_api_app" + agentSelfTelemetryCirconusAPIToken = "circonus_api_token" + agentSelfTelemetryCirconusAPIURL = "circonus_api_url" + agentSelfTelemetryCirconusBrokerID = "circonus_broker_id" + agentSelfTelemetryCirconusBrokerSelectTag = "circonus_select_tag" + agentSelfTelemetryCirconusCheckDisplayName = "circonus_display_name" + agentSelfTelemetryCirconusCheckForceMetricActiation = "circonus_force_metric_activation" + agentSelfTelemetryCirconusCheckID = "circonus_check_id" + agentSelfTelemetryCirconusCheckInstanceID = "circonus_instance_id" + agentSelfTelemetryCirconusCheckSearchTag = "circonus_search_tag" + agentSelfTelemetryCirconusCheckSubmissionURL = "circonus_submission_url" + agentSelfTelemetryCirconusCheckTags = "circonus_tags" + agentSelfTelemetryCirconusSubmissionInterval = "circonus_submission_interval" + + agentSelfTelemetryDogStatsdAddr = "dogstatsd_addr" + agentSelfTelemetryDogStatsdTags = "dogstatsd_tags" + agentSelfTelemetryEnableHostname = "enable_hostname" + agentSelfTelemetryStatsdAddr = "statsd_addr" + agentSelfTelemetryStatsiteAddr = "statsite_addr" + agentSelfTelemetryStatsitePrefix = "statsite_prefix" +) + +const ( + agentSelfUnixSocketGroup = "group" + agentSelfUnixSocketMode = "mode" + agentSelfUnixSocketUser = "user" ) -// Schema for consul's /v1/agent/self endpoint -var agentSelfMap = map[typeKey]*typeEntry{ - agentSelfACLDatacenter: { - APIName: "ACLDatacenter", - SchemaName: "acl_datacenter", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfACLDefaultPolicy: { - APIName: "ACLDefaultPolicy", - SchemaName: "acl_default_policy", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfACLDisableTTL: { - APIName: "ACLDisabledTTL", - SchemaName: "acl_disable_ttl", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfACLDownPolicy: { - APIName: "ACLDownPolicy", - SchemaName: "acl_down_policy", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfACLEnforceVersion8: { - APIName: "ACLEnforceVersion8", - SchemaName: "acl_enforce_version_8", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfACLTTL: { - APIName: "ACLTTL", - SchemaName: "acl_ttl", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfAddresses: { - APIName: "Addresses", - SchemaName: "addresses", - Source: sourceAPIResult, - Type: schema.TypeMap, - }, - agentSelfAdvertiseAddr: { - APIName: "AdvertiseAddr", - SchemaName: "advertise_addr", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfAdvertiseAddrs: { - APIName: "AdvertiseAddrs", - SchemaName: "advertise_addrs", - Source: sourceAPIResult, - Type: schema.TypeMap, - }, - agentSelfAdvertiseAddrWAN: { - APIName: "AdvertiseAddrWan", - SchemaName: "advertise_addr_wan", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - // Omitting the following since they've been depreciated: - // - // "AtlasInfrastructure": "", - // "AtlasEndpoint": "", - agentSelfAtlasJoin: { - APIName: "AtlasJoin", - SchemaName: "atlas_join", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfBindAddr: { - APIName: "BindAddr", - SchemaName: "bind_addr", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfBootstrap: { - APIName: "Bootstrap", - SchemaName: "bootstrap", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfBootstrapExpect: { - APIName: "BootstrapExpect", - SchemaName: "bootstrap_expect", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfCAFile: { - APIName: "CAFile", - SchemaName: "ca_file", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfCertFile: { - APIName: "CertFile", - SchemaName: "cert_file", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfCheckDeregisterIntervalMin: { - APIName: "CheckDeregisterIntervalMin", - SchemaName: "check_deregister_interval_min", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfCheckDisableAnonymousSignature: { - APIName: "DisableAnonymousSignature", - SchemaName: "disable_anonymous_signature", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfCheckDisableRemoteExec: { - APIName: "DisableRemoteExec", - SchemaName: "disable_remote_exec", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfCheckReapInterval: { - APIName: "CheckReapInterval", - SchemaName: "check_reap_interval", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfCheckUpdateInterval: { - APIName: "CheckUpdateInterval", - SchemaName: "check_update_interval", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfClientAddr: { - APIName: "ClientAddr", - SchemaName: "client_addr", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfDNSConfig: { - APIName: "DNSConfig", - SchemaName: "dns_config", - Source: sourceAPIResult, - Type: schema.TypeMap, - SetMembers: map[typeKey]*typeEntry{ - agentSelfDNSAllowStale: { - APIName: "AllowStale", - SchemaName: "allow_stale", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfDNSDisableCompression: { - APIName: "DisableCompression", - SchemaName: "disable_compression", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfDNSEnableTruncate: { - APIName: "EnableTruncate", - SchemaName: "enable_truncate", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfDNSMaxStale: { - APIName: "MaxStale", - SchemaName: "max_stale", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfDNSNodeTTL: { - APIName: "NodeTTL", - SchemaName: "node_ttl", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfDNSOnlyPassing: { - APIName: "OnlyPassing", - SchemaName: "only_passing", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfRecursorTimeout: { - APIName: "RecursorTimeout", - SchemaName: "recursor_timeout", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfServiceTTL: { - APIName: "ServiceTTL", - SchemaName: "service_ttl", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfDNSUDPAnswerLimit: { - APIName: "UDPAnswerLimit", - SchemaName: "udp_answer_limit", - Source: sourceAPIResult, - Type: schema.TypeFloat, +func dataSourceConsulAgentSelf() *schema.Resource { + return &schema.Resource{ + Read: dataSourceConsulAgentSelfRead, + Schema: map[string]*schema.Schema{ + agentSelfACLDatacenter: { + Computed: true, + Type: schema.TypeString, }, - }, - }, - agentSelfDataDir: { - APIName: "DataDir", - SchemaName: "data_dir", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfDatacenter: { - APIName: "Datacenter", - SchemaName: "datacenter", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfDevMode: { - APIName: "DevMode", - SchemaName: "dev_mode", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfDisableCoordinates: { - APIName: "DisableCoordinates", - SchemaName: "coordinates", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfDisableUpdateCheck: { - APIName: "DisableUpdateCheck", - SchemaName: "update_check", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfDNSRecursors: { - APIName: "DNSRecursors", - APIAliases: []apiAttr{"DNSRecursor"}, - SchemaName: "dns_recursors", - Source: sourceAPIResult, - Type: schema.TypeList, - }, - agentSelfDomain: { - APIName: "Domain", - SchemaName: "domain", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfEnableDebug: { - APIName: "EnableDebug", - SchemaName: "debug", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfEnableSyslog: { - APIName: "EnableSyslog", - SchemaName: "syslog", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfEnableUI: { - APIName: "EnableUi", - SchemaName: "ui", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - // "HTTPAPIResponseHeaders": nil, - agentSelfID: { - APIName: "NodeID", - SchemaName: "id", - Source: sourceAPIResult, - Type: schema.TypeString, - ValidateFuncs: []interface{}{ - validateRegexp(`(?i)^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$`), - }, - APITest: apiTestID, - APIToState: apiToStateID, - }, - agentSelfKeyFile: { - APIName: "KeyFile", - SchemaName: "key_file", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfLeaveOnInt: { - APIName: "SkipLeaveOnInt", - SchemaName: "leave_on_int", - Source: sourceAPIResult, - Type: schema.TypeBool, - APITest: apiTestBool, - APIToState: negateBoolToState(apiToStateBool), - }, - agentSelfLeaveOnTerm: { - APIName: "LeaveOnTerm", - SchemaName: "leave_on_term", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfLogLevel: { - APIName: "LogLevel", - SchemaName: "log_level", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfName: { - APIName: "NodeName", - SchemaName: "name", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfPerformance: { - APIName: "Performance", - SchemaName: "performance", - Source: sourceAPIResult, - Type: schema.TypeMap, - SetMembers: map[typeKey]*typeEntry{ - agentSelfPerformanceRaftMultiplier: { - APIName: "RaftMultiplier", - SchemaName: "raft_multiplier", - Source: sourceAPIResult, - Type: schema.TypeFloat, + agentSelfACLDefaultPolicy: { + Computed: true, + Type: schema.TypeString, }, - }, - }, - agentSelfPidFile: { - APIName: "PidFile", - SchemaName: "pid_file", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfPorts: { - APIName: "Ports", - SchemaName: "ports", - Source: sourceAPIResult, - Type: schema.TypeMap, - SetMembers: map[typeKey]*typeEntry{ - agentSelfPortsDNS: { - APIName: "DNS", - SchemaName: "dns", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfPortsHTTP: { - APIName: "HTTP", - SchemaName: "http", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfPortsHTTPS: { - APIName: "HTTPS", - SchemaName: "https", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfPortsRPC: { - APIName: "RPC", - SchemaName: "rpc", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfPortsSerfLAN: { - APIName: "SerfLan", - SchemaName: "serf_lan", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfPortsSerfWAN: { - APIName: "SerfWan", - SchemaName: "serf_wan", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfPortsServer: { - APIName: "Server", - SchemaName: "server", - Source: sourceAPIResult, - Type: schema.TypeFloat, + agentSelfACLDisabledTTL: { + Computed: true, + Type: schema.TypeString, + ValidateFunc: makeValidationFunc(agentSelfACLDisabledTTL, validatorInputs{ + validateDurationMin("0ns"), + }), }, - }, - }, - agentSelfProtocol: { - APIName: "Protocol", - SchemaName: "protocol", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfReconnectTimeoutLAN: { - APIName: "ReconnectTimeoutLan", - SchemaName: "reconnect_timeout_lan", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfReconnectTimeoutWAN: { - APIName: "ReconnectTimeoutWan", - SchemaName: "reconnect_timeout_wan", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfRejoinAfterLeave: { - APIName: "RejoinAfterLeave", - SchemaName: "rejoin_after_leave", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - // "RetryIntervalWanRaw": "", - agentSelfRetryJoin: { - APIName: "RetryJoin", - SchemaName: "retry_join", - Source: sourceAPIResult, - Type: schema.TypeList, - }, - agentSelfRetryJoinWAN: { - APIName: "RetryJoinWan", - SchemaName: "retry_join_wan", - Source: sourceAPIResult, - Type: schema.TypeList, - }, - agentSelfRetryMaxAttempts: { - APIName: "RetryMaxAttempts", - SchemaName: "retry_max_attempts", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfRetryMaxAttemptsWAN: { - APIName: "RetryMaxAttemptsWan", - SchemaName: "retry_max_attempts_wan", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfRetryJoinEC2: { - APIName: "RetryJoinEC2", - SchemaName: "retry_join_ec2", - Source: sourceAPIResult, - Type: schema.TypeMap, - }, - agentSelfRetryJoinGCE: { - APIName: "RetryJoinGCE", - SchemaName: "retry_join_GCE", - Source: sourceAPIResult, - Type: schema.TypeMap, - }, - agentSelfRevision: { - APIName: "Revision", - SchemaName: "revision", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfSerfLANBindAddr: { - APIName: "SerfLanBindAddr", - SchemaName: "serf_lan_bind_addr", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfSerfWANBindAddr: { - APIName: "SerfWanBindAddr", - SchemaName: "serf_wan_bind_addr", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfServer: { - APIName: "Server", - SchemaName: "server", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfServerName: { - APIName: "ServerName", - SchemaName: "server_name", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfSessionTTLMin: { - APIName: "SessionTTLMin", - SchemaName: "session_ttl_min", - Source: sourceAPIResult, - Type: schema.TypeFloat, - }, - agentSelfStartJoin: { - APIName: "StartJoin", - SchemaName: "start_join", - Source: sourceAPIResult, - Type: schema.TypeList, - }, - agentSelfStartJoinWAN: { - APIName: "StartJoinWan", - SchemaName: "start_join_wan", - Source: sourceAPIResult, - Type: schema.TypeList, - }, - agentSelfSyslogFacility: { - APIName: "SyslogFacility", - SchemaName: "syslog_facility", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTaggedAddresses: { - APIName: "TaggedAddresses", - SchemaName: "tagged_addresses", - Source: sourceAPIResult, - Type: schema.TypeMap, - SetMembers: map[typeKey]*typeEntry{ - agentSelfTaggedAddressesLAN: { - APIName: "LAN", - SchemaName: "lan", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTaggedAddressesWAN: { - APIName: "WAN", - SchemaName: "wan", - Source: sourceAPIResult, - Type: schema.TypeString, + agentSelfACLDownPolicy: { + Computed: true, + Type: schema.TypeString, }, - }, - }, - agentSelfTelemetry: { - APIName: "Telemetry", - SchemaName: "telemetry", - Source: sourceAPIResult, - Type: schema.TypeMap, - SetMembers: map[typeKey]*typeEntry{ - agentSelfTelemetryCirconusAPIApp: { - APIName: "CirconusAPIApp", - SchemaName: "circonus_api_app", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryCirconusAPIURL: { - APIName: "CirconusAPIURL", - SchemaName: "circonus_api_url", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryCirconusBrokerID: { - APIName: "CirconusBrokerID", - SchemaName: "circonus_broker_id", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryCirconusBrokerSelectTag: { - APIName: "CirconusBrokerSelectTag", - SchemaName: "circonus_broker_select_tag", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryCirconusCheckDisplayName: { - APIName: "CirconusCheckDisplayName", - SchemaName: "circonus_check_display_name", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryCirconusCheckForceMetricActiation: { - APIName: "CirconusCheckForceMetricActivation", - SchemaName: "circonus_check_force_metric_activation", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryCirconusCheckID: { - APIName: "CirconusCheckID", - SchemaName: "circonus_check_id", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryCirconusCheckInstanceID: { - APIName: "CirconusCheckInstanceID", - SchemaName: "circonus_check_instance_id", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryCirconusCheckSearchTag: { - APIName: "CirconusCheckSearchTag", - SchemaName: "circonus_check_search_tag", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryCirconusCheckSubmissionURL: { - APIName: "CirconusCheckSubmissionURL", - SchemaName: "circonus_check_submission_url", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryCirconusCheckTags: { - APIName: "CirconusCheckTags", - SchemaName: "circonus_check_tags", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryCirconusSubmissionInterval: { - APIName: "CirconusSubmissionInterval", - SchemaName: "circonus_submission_interval", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryDisableHostname: { - APIName: "DisableHostname", - SchemaName: "disable_hostname", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfTelemetryDogStatsdAddr: { - APIName: "DogStatsdAddr", - SchemaName: "dog_statsd_addr", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryDogStatsdTags: { - APIName: "DogStatsdTags", - SchemaName: "dog_statsd_tags", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryStatsdAddr: { - APIName: "StatsdTags", - SchemaName: "statsd_tags", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryStatsiteAddr: { - APIName: "StatsiteAddr", - SchemaName: "statsite_addr", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTelemetryStatsitePrefix: { - APIName: "StatsitePrefix", - SchemaName: "statsite_prefix", - Source: sourceAPIResult, - Type: schema.TypeString, + agentSelfACLEnforceVersion8: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfACLTTL: { + Computed: true, + Type: schema.TypeString, + ValidateFunc: makeValidationFunc(agentSelfACLTTL, validatorInputs{ + validateDurationMin("0ns"), + }), + }, + agentSelfAddresses: { + Computed: true, + Type: schema.TypeMap, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + agentSelfSchemaPortsDNS: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfSchemaPortsHTTP: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfSchemaPortsHTTPS: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfSchemaPortsRPC: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + agentSelfAdvertiseAddr: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfAdvertiseAddrs: { + Computed: true, + Type: schema.TypeMap, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + agentSelfSchemaPortsSerfLAN: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfSchemaPortsSerfWAN: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfSchemaPortsRPC: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + agentSelfAdvertiseAddrWAN: { + Computed: true, + Type: schema.TypeString, + }, + // Omitting the following since they've been depreciated: + // + // "AtlasInfrastructure": "", + // "AtlasEndpoint": "", + agentSelfAtlasJoin: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfBindAddr: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfBootstrapMode: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfBootstrapExpect: { + Computed: true, + Type: schema.TypeInt, + }, + agentSelfCheckDeregisterIntervalMin: { + Computed: true, + Type: schema.TypeString, + ValidateFunc: makeValidationFunc(agentSelfCheckDeregisterIntervalMin, validatorInputs{ + validateDurationMin("0ns"), + }), + }, + agentSelfCheckReapInterval: { + Computed: true, + Type: schema.TypeString, + ValidateFunc: makeValidationFunc(agentSelfCheckReapInterval, validatorInputs{ + validateDurationMin("0ns"), + }), + }, + agentSelfCheckUpdateInterval: { + Computed: true, + Type: schema.TypeString, + ValidateFunc: makeValidationFunc(agentSelfCheckUpdateInterval, validatorInputs{ + validateDurationMin("0ns"), + }), + }, + agentSelfClientAddr: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfDNSConfig: { + Computed: true, + Type: schema.TypeMap, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + agentSelfDNSAllowStale: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfDNSEnableCompression: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfDNSEnableTruncate: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfDNSMaxStale: { + Computed: true, + Type: schema.TypeString, + ValidateFunc: makeValidationFunc(agentSelfDNSMaxStale, validatorInputs{ + validateDurationMin("0ns"), + }), + }, + agentSelfDNSNodeTTL: { + Computed: true, + Type: schema.TypeString, + ValidateFunc: makeValidationFunc(agentSelfDNSNodeTTL, validatorInputs{ + validateDurationMin("0ns"), + }), + }, + agentSelfDNSOnlyPassing: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfDNSRecursorTimeout: { + Computed: true, + Type: schema.TypeString, + ValidateFunc: makeValidationFunc(agentSelfDNSRecursorTimeout, validatorInputs{ + validateDurationMin("0ns"), + }), + }, + agentSelfDNSServiceTTL: { + Computed: true, + Type: schema.TypeString, + ValidateFunc: makeValidationFunc(agentSelfDNSServiceTTL, validatorInputs{ + validateDurationMin("0ns"), + }), + }, + agentSelfDNSUDPAnswerLimit: { + Computed: true, + Type: schema.TypeInt, + }, + }, + }, + }, + agentSelfDataDir: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfDatacenter: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfDevMode: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfEnableAnonymousSignature: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfEnableCoordinates: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfEnableRemoteExec: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfEnableUpdateCheck: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfDNSRecursors: { + Computed: true, + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + agentSelfDomain: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfEnableDebug: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfEnableSyslog: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfEnableUI: { + Computed: true, + Type: schema.TypeBool, + }, + // "HTTPAPIResponseHeaders": nil, // TODO(sean@) + agentSelfID: { + Computed: true, + Type: schema.TypeString, + ValidateFunc: makeValidationFunc(agentSelfID, validatorInputs{ + validateRegexp(`(?i)^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$`), + }), + }, + agentSelfLeaveOnInt: { + Computed: true, + Type: schema.TypeBool, }, + agentSelfLeaveOnTerm: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfLogLevel: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfName: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfPerformance: { + Computed: true, + Type: schema.TypeMap, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + agentSelfPerformanceRaftMultiplier: { + Computed: true, + Type: schema.TypeString, // FIXME(sean@): should be schema.TypeInt + ValidateFunc: makeValidationFunc(agentSelfPerformanceRaftMultiplier, validatorInputs{ + validateIntMin(0), + }), + }, + }, + }, + }, + agentSelfPidFile: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfPorts: { + Computed: true, + Type: schema.TypeMap, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + agentSelfSchemaPortsDNS: { + Computed: true, + Type: schema.TypeInt, + ValidateFunc: makeValidationFunc(agentSelfSchemaPortsDNS, validatorInputs{ + validateIntMin(1), + validateIntMax(65535), + }), + }, + agentSelfSchemaPortsHTTP: { + Computed: true, + Type: schema.TypeInt, + ValidateFunc: makeValidationFunc(agentSelfSchemaPortsHTTP, validatorInputs{ + validateIntMin(1), + validateIntMax(65535), + }), + }, + agentSelfSchemaPortsHTTPS: { + Computed: true, + Type: schema.TypeInt, + ValidateFunc: makeValidationFunc(agentSelfSchemaPortsHTTPS, validatorInputs{ + validateIntMin(1), + validateIntMax(65535), + }), + }, + agentSelfSchemaPortsRPC: { + Computed: true, + Type: schema.TypeInt, + ValidateFunc: makeValidationFunc(agentSelfSchemaPortsRPC, validatorInputs{ + validateIntMin(1), + validateIntMax(65535), + }), + }, + agentSelfSchemaPortsSerfLAN: { + Computed: true, + Type: schema.TypeInt, + ValidateFunc: makeValidationFunc(agentSelfSchemaPortsSerfLAN, validatorInputs{ + validateIntMin(1), + validateIntMax(65535), + }), + }, + agentSelfSchemaPortsSerfWAN: { + Computed: true, + Type: schema.TypeInt, + ValidateFunc: makeValidationFunc(agentSelfSchemaPortsSerfWAN, validatorInputs{ + validateIntMin(1), + validateIntMax(65535), + }), + }, + agentSelfSchemaPortsServer: { + Computed: true, + Type: schema.TypeInt, + ValidateFunc: makeValidationFunc(agentSelfSchemaPortsServer, validatorInputs{ + validateIntMin(1), + validateIntMax(65535), + }), + }, + }, + }, + }, + agentSelfProtocol: { + Computed: true, + Type: schema.TypeInt, + }, + agentSelfReconnectTimeoutLAN: { + Computed: true, + Type: schema.TypeString, + ValidateFunc: makeValidationFunc(agentSelfReconnectTimeoutLAN, validatorInputs{ + validateDurationMin("0ns"), + }), + }, + agentSelfReconnectTimeoutWAN: { + Computed: true, + Type: schema.TypeString, + ValidateFunc: makeValidationFunc(agentSelfReconnectTimeoutWAN, validatorInputs{ + validateDurationMin("0ns"), + }), + }, + agentSelfRejoinAfterLeave: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfRetryJoin: { + Computed: true, + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + agentSelfRetryJoinWAN: { + Computed: true, + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + agentSelfRetryMaxAttempts: { + Computed: true, + Type: schema.TypeInt, + }, + agentSelfRetryMaxAttemptsWAN: { + Computed: true, + Type: schema.TypeInt, + }, + agentSelfRetryJoinEC2: { + Computed: true, + Type: schema.TypeMap, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + agentSelfRetryJoinAWSRegion: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfRetryJoinAWSTagKey: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfRetryJoinAWSTagValue: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfRetryJoinAWSAccessKeyID: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + agentSelfRetryJoinAWSSecretAccessKey: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + }, + }, + }, + agentSelfRetryJoinGCE: { + Computed: true, + Type: schema.TypeMap, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + agentSelfRetryJoinGCEProjectName: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfRetryJoinGCEZonePattern: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfRetryJoinGCETagValue: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfRetryJoinGCECredentialsFile: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + agentSelfSerfLANBindAddr: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfSerfWANBindAddr: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfServerMode: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfServerName: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfSessionTTLMin: { + Computed: true, + Type: schema.TypeString, + ValidateFunc: makeValidationFunc(agentSelfSessionTTLMin, validatorInputs{ + validateDurationMin("0ns"), + }), + }, + agentSelfStartJoin: { + Computed: true, + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + agentSelfStartJoinWAN: { + Computed: true, + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + agentSelfSyslogFacility: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfTaggedAddresses: { + Computed: true, + Type: schema.TypeMap, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + agentSelfTaggedAddressesLAN: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfTaggedAddressesWAN: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + agentSelfTelemetry: { + Computed: true, + Type: schema.TypeMap, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + agentSelfTelemetryCirconusAPIApp: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfTelemetryCirconusAPIToken: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfTelemetryCirconusAPIURL: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfTelemetryCirconusBrokerID: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfTelemetryCirconusBrokerSelectTag: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfTelemetryCirconusCheckDisplayName: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfTelemetryCirconusCheckID: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfTelemetryCirconusCheckInstanceID: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfTelemetryCirconusCheckSearchTag: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfTelemetryCirconusCheckSubmissionURL: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfTelemetryCirconusCheckTags: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfTelemetryCirconusCheckForceMetricActiation: &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + }, + agentSelfTelemetryCirconusSubmissionInterval: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + ValidateFunc: makeValidationFunc(agentSelfTelemetryCirconusSubmissionInterval, validatorInputs{ + validateDurationMin("0ns"), + }), + }, + agentSelfTelemetryEnableHostname: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfTelemetryDogStatsdAddr: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfTelemetryDogStatsdTags: &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + agentSelfTelemetryStatsdAddr: { + Type: schema.TypeString, + Computed: true, + }, + agentSelfTelemetryStatsiteAddr: { + Type: schema.TypeString, + Computed: true, + }, + agentSelfTelemetryStatsitePrefix: { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + agentSelfTLSCAFile: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfTLSCertFile: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfTLSKeyFile: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfTLSMinVersion: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfTLSVerifyIncoming: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfTLSVerifyServerHostname: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfTLSVerifyOutgoing: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfTranslateWANAddrs: { + Computed: true, + Type: schema.TypeBool, + }, + agentSelfUIDir: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfUnixSockets: { + Computed: true, + Type: schema.TypeMap, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + agentSelfUnixSocketUser: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfUnixSocketGroup: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + agentSelfUnixSocketMode: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + agentSelfVersion: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfVersionPrerelease: { + Computed: true, + Type: schema.TypeString, + }, + agentSelfVersionRevision: { + Computed: true, + Type: schema.TypeString, + }, + // "Watches": nil, }, - }, - agentSelfTLSMinVersion: { - APIName: "TLSMinVersion", - SchemaName: "tls_min_version", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfTranslateWANAddrs: { - APIName: "TranslateWanAddrs", - SchemaName: "translate_wan_addrs", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfUIDir: { - APIName: "UiDir", - SchemaName: "ui_dir", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfUnixSockets: { - APIName: "UnixSockets", - SchemaName: "unix_sockets", - Source: sourceAPIResult, - Type: schema.TypeMap, - }, - agentSelfVerifyIncoming: { - APIName: "VerifyIncoming", - SchemaName: "verify_incoming", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfVerifyServerHostname: { - APIName: "VerifyServerHostname", - SchemaName: "verify_server_hostname", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfVerifyOutgoing: { - APIName: "VerifyOutgoing", - SchemaName: "verify_outgoing", - Source: sourceAPIResult, - Type: schema.TypeBool, - }, - agentSelfVersion: { - APIName: "Version", - SchemaName: "version", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - agentSelfVersionPrerelease: { - APIName: "VersionPrerelease", - SchemaName: "version_prerelease", - Source: sourceAPIResult, - Type: schema.TypeString, - }, - // "Watches": nil, -} - -func dataSourceConsulAgentSelf() *schema.Resource { - return &schema.Resource{ - Read: dataSourceConsulAgentSelfRead, - Schema: typeEntryMapToSchema(agentSelfMap), } } @@ -838,35 +832,612 @@ func dataSourceConsulAgentSelfRead(d *schema.ResourceData, meta interface{}) err return fmt.Errorf("No %s info available within provider's agent/self endpoint", apiAgentConfig) } - // TODO(sean@): It'd be nice if this data source had a way of filtering out - // irrelevant data so only the important bits are persisted in the state file. - // Something like an attribute mask or even a regexp of matching schema names - // would be sufficient in the most basic case. Food for thought. - dataSourceWriter := newStateWriter(d) + // Pull the datacenter first because we use it when setting the ID + var dc string + if v, found := cfg["Datacenter"]; found { + dc = v.(string) + } + + const idKeyFmt = "agent-self-%s" + d.SetId(fmt.Sprintf(idKeyFmt, dc)) + + if v, found := cfg["ACLDatacenter"]; found { + d.Set(agentSelfACLDatacenter, v.(string)) + } + + if v, found := cfg["ACLDefaultPolicy"]; found { + d.Set(agentSelfACLDefaultPolicy, v.(string)) + } + + if v, found := cfg["ACLDisabledTTL"]; found { + dur := time.Duration(int64(v.(float64))) + d.Set(agentSelfACLDisabledTTL, dur.String()) + } + + if v, found := cfg["ACLDownPolicy"]; found { + d.Set(agentSelfACLDownPolicy, v.(string)) + } + + if v, found := cfg["ACLEnforceVersion8"]; found { + d.Set(agentSelfACLEnforceVersion8, v.(bool)) + } + + if v, found := cfg["ACLTTL"]; found { + dur := time.Duration(int64(v.(float64))) + d.Set(agentSelfACLTTL, dur.String()) + } + + if v, found := cfg["Addresses"]; found { + addrs := v.(map[string]interface{}) + + m := make(map[string]interface{}, len(addrs)) + + if v, found := addrs["DNS"]; found { + m[agentSelfSchemaPortsDNS] = v.(string) + } + + if v, found := addrs["HTTP"]; found { + m[agentSelfSchemaPortsHTTP] = v.(string) + } + + if v, found := addrs["HTTPS"]; found { + m[agentSelfSchemaPortsHTTPS] = v.(string) + } + + if v, found := addrs["RPC"]; found { + m[agentSelfSchemaPortsRPC] = v.(string) + } + + if err := d.Set(agentSelfAddresses, m); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Unable to set %s: {{err}}", agentSelfAddresses), err) + } + } + + if v, found := cfg["AdvertiseAddr"]; found { + d.Set(agentSelfAdvertiseAddr, v.(string)) + } + + if v, found := cfg["AdvertiseAddrs"]; found { + addrs := v.(map[string]interface{}) + + m := make(map[string]interface{}, len(addrs)) + + if v, found := addrs["SerfLan"]; found && v != nil { + m[agentSelfSchemaPortsSerfLAN] = v.(string) + } + + if v, found := addrs["SerfWan"]; found && v != nil { + m[agentSelfSchemaPortsSerfWAN] = v.(string) + } + + if v, found := addrs["RPC"]; found && v != nil { + m[agentSelfSchemaPortsRPC] = v.(string) + } + + if err := d.Set(agentSelfAdvertiseAddrs, m); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Unable to set %s: {{err}}", agentSelfAdvertiseAddrs), err) + } + } + + if v, found := cfg["AtlasJoin"]; found { + d.Set(agentSelfAtlasJoin, v.(bool)) + } + + if v, found := cfg["BindAddr"]; found { + d.Set(agentSelfBindAddr, v.(string)) + } + + if v, found := cfg["Bootstrap"]; found { + d.Set(agentSelfBootstrapMode, v.(bool)) + } + + if v, found := cfg["BootstrapExpect"]; found { + d.Set(agentSelfBootstrapExpect, int(v.(float64))) + } + + if v, found := cfg["CheckDeregisterIntervalMin"]; found { + dur := time.Duration(int64(v.(float64))) + d.Set(agentSelfCheckDeregisterIntervalMin, dur.String()) + } + + if v, found := cfg["CheckReapInterval"]; found { + dur := time.Duration(int64(v.(float64))) + d.Set(agentSelfCheckReapInterval, dur.String()) + } + + if v, found := cfg["CheckUpdateInterval"]; found { + dur := time.Duration(int64(v.(float64))) + d.Set(agentSelfCheckUpdateInterval, dur.String()) + } + + if v, found := cfg["ClientAddr"]; found { + d.Set(agentSelfClientAddr, v.(string)) + } + + if v, found := cfg["DNS"]; found { + dnsOpts := v.(map[string]interface{}) + + m := make(map[string]interface{}, len(dnsOpts)) + + if v, found := dnsOpts["AllowStale"]; found { + m[agentSelfDNSAllowStale] = v.(bool) + } + + if v, found := dnsOpts["DisableCompression"]; found { + m[agentSelfDNSEnableCompression] = !v.(bool) + } + + if v, found := dnsOpts["EnableTruncate"]; found { + m[agentSelfDNSEnableTruncate] = v.(bool) + } + + if v, found := dnsOpts["MaxStale"]; found { + dur := time.Duration(int64(v.(float64))) + m[agentSelfDNSMaxStale] = dur.String() + } + + if v, found := dnsOpts["NodeTTL"]; found { + dur := time.Duration(int64(v.(float64))) + m[agentSelfDNSNodeTTL] = dur.String() + } + + if v, found := dnsOpts["OnlyPassing"]; found { + m[agentSelfDNSOnlyPassing] = v.(bool) + } + + if v, found := dnsOpts["RecursorTimeout"]; found { + dur := time.Duration(int64(v.(float64))) + m[agentSelfDNSRecursorTimeout] = dur.String() + } - for k, e := range agentSelfMap { - apiTest := e.APITest - if apiTest == nil { - apiTest = e.LookupDefaultTypeHandler().APITest + if v, found := dnsOpts["ServiceTTL"]; found { + dur := time.Duration(int64(v.(float64))) + m[agentSelfDNSServiceTTL] = dur.String() } - if apiTest == nil { - panic(fmt.Sprintf("PROVIDER BUG: %v missing APITest method", k)) + + if v, found := dnsOpts["UDPAnswerLimit"]; found { + m[agentSelfDNSServiceTTL] = v.(int) + } + + if err := d.Set(agentSelfDNSConfig, m); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Unable to set %s: {{err}}", agentSelfDNSConfig), err) } + } + + { + var l []interface{} - apiToState := e.APIToState - if apiToState == nil { - apiToState = e.LookupDefaultTypeHandler().APIToState + if v, found := cfg["DNSRecursors"]; found { + l = make([]interface{}, 0, len(v.([]interface{}))+1) + l = append(l, v.([]interface{})...) } - if apiToState == nil { - panic(fmt.Sprintf("PROVIDER BUG: %v missing APIToState method", k)) + + if v, found := cfg["DNSRecursor"]; found { + l = append([]interface{}{v.(string)}, l...) } - if v, ok := apiTest(e, cfg); ok { - if err := apiToState(e, v, dataSourceWriter); err != nil { - return errwrap.Wrapf(fmt.Sprintf("error writing %q's data to state: {{err}}", e.SchemaName), err) + if len(l) > 0 { + if err := d.Set(agentSelfDNSRecursors, l); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Unable to set %s: {{err}}", agentSelfDNSRecursors), err) } } } + if v, found := cfg["DataDir"]; found { + d.Set(agentSelfDataDir, v.(string)) + } + + if len(dc) > 0 { + d.Set(agentSelfDatacenter, dc) + } + + if v, found := cfg["DevMode"]; found { + d.Set(agentSelfDevMode, v.(bool)) + } + + if v, found := cfg["DisableAnonymousSignature"]; found { + d.Set(agentSelfEnableAnonymousSignature, !v.(bool)) + } + + if v, found := cfg["DisableCoordinates"]; found { + d.Set(agentSelfEnableCoordinates, !v.(bool)) + } + + if v, found := cfg["DisableRemoteExec"]; found { + d.Set(agentSelfEnableRemoteExec, !v.(bool)) + } + + if v, found := cfg["DisableUpdateCheck"]; found { + d.Set(agentSelfEnableUpdateCheck, !v.(bool)) + } + + if v, found := cfg["Domain"]; found { + d.Set(agentSelfDomain, v.(string)) + } + + if v, found := cfg["EnableDebug"]; found { + d.Set(agentSelfEnableDebug, v.(bool)) + } + + if v, found := cfg["EnableSyslog"]; found { + d.Set(agentSelfEnableSyslog, v.(bool)) + } + + if v, found := cfg["EnableUi"]; found { + d.Set(agentSelfEnableUI, v.(bool)) + } + + if v, found := cfg["id"]; found { + d.Set(agentSelfID, v.(string)) + } + + if v, found := cfg["SkipLeaveOnInt"]; found { + d.Set(agentSelfLeaveOnInt, !v.(bool)) + } + + if v, found := cfg["LeaveOnTerm"]; found { + d.Set(agentSelfLeaveOnTerm, v.(bool)) + } + + if v, found := cfg["LogLevel"]; found { + d.Set(agentSelfLogLevel, v.(string)) + } + + if v, found := cfg["NodeName"]; found { + d.Set(agentSelfName, v.(string)) + } + + if v, found := cfg["Performance"]; found { + cfgs := v.(map[string]interface{}) + + m := make(map[string]interface{}, len(cfgs)) + + if v, found := cfgs["RaftMultiplier"]; found { + m[agentSelfPerformanceRaftMultiplier] = strconv.FormatFloat(v.(float64), 'g', -1, 64) + } + + if err := d.Set(agentSelfPerformance, m); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Unable to set %s: {{err}}", agentSelfPerformance), err) + } + } + + if v, found := cfg["PidFile"]; found { + d.Set(agentSelfPidFile, v.(string)) + } + + if v, found := cfg["Ports"]; found { + cfgs := v.(map[string]interface{}) + + m := make(map[string]interface{}, len(cfgs)) + + if v, found := cfgs[agentSelfAPIPortsDNS]; found { + m[agentSelfSchemaPortsDNS] = int(v.(float64)) + } + + if v, found := cfgs[agentSelfAPIPortsHTTP]; found { + m[agentSelfSchemaPortsHTTP] = int(v.(float64)) + } + + if v, found := cfgs[agentSelfAPIPortsHTTPS]; found { + m[agentSelfSchemaPortsHTTPS] = int(v.(float64)) + } + + if v, found := cfgs[agentSelfAPIPortsRPC]; found { + m[agentSelfSchemaPortsRPC] = int(v.(float64)) + } + + if v, found := cfgs[agentSelfAPIPortsSerfLAN]; found { + m[agentSelfSchemaPortsSerfLAN] = int(v.(float64)) + } + + if v, found := cfgs[agentSelfAPIPortsSerfWAN]; found { + m[agentSelfSchemaPortsSerfWAN] = int(v.(float64)) + } + + if v, found := cfgs[agentSelfAPIPortsServer]; found { + m[agentSelfSchemaPortsServer] = int(v.(float64)) + } + + if err := d.Set(agentSelfPorts, m); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Unable to set %s: {{err}}", agentSelfPorts), err) + } + } + + if v, found := cfg["Protocol"]; found { + d.Set(agentSelfProtocol, int(v.(float64))) + } + + if v, found := cfg["ReconnectTimeoutLan"]; found { + dur := time.Duration(int64(v.(float64))) + d.Set(agentSelfReconnectTimeoutLAN, dur.String()) + } + + if v, found := cfg["ReconnectTimeoutWan"]; found { + dur := time.Duration(int64(v.(float64))) + d.Set(agentSelfReconnectTimeoutWAN, dur.String()) + } + + if v, found := cfg["RejoinAfterLeave"]; found { + d.Set(agentSelfRejoinAfterLeave, v.(bool)) + } + + if v, found := cfg["RetryJoin"]; found { + l := make([]string, 0, len(v.([]interface{}))) + for _, e := range v.([]interface{}) { + l = append(l, e.(string)) + } + + if err := d.Set(agentSelfRetryJoin, l); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Unable to set %s: {{err}}", agentSelfRetryJoin), err) + } + } + + if v, found := cfg["RetryJoinEC2"]; found { + ec2Config := v.(map[string]interface{}) + + m := make(map[string]interface{}, len(ec2Config)) + + if v, found := ec2Config["Region"]; found { + m[agentSelfRetryJoinAWSRegion] = v.(string) + } + + if v, found := ec2Config["TagKey"]; found { + m[agentSelfRetryJoinAWSTagKey] = v.(string) + } + + if v, found := ec2Config["TagValue"]; found { + m[agentSelfRetryJoinAWSTagValue] = v.(string) + } + + if v, found := ec2Config["AccessKeyID"]; found { + m[agentSelfRetryJoinAWSAccessKeyID] = v.(string) + } + + if v, found := ec2Config["SecretAccessKey"]; found { + m[agentSelfRetryJoinAWSSecretAccessKey] = v.(string) + } + + if err := d.Set(agentSelfRetryJoinEC2, m); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Unable to set %s: {{err}}", agentSelfRetryJoinEC2), err) + } + } + + if v, found := cfg["RetryJoinWan"]; found { + l := make([]string, 0, len(v.([]interface{}))) + for _, e := range v.([]interface{}) { + l = append(l, e.(string)) + } + + if err := d.Set(agentSelfRetryJoinWAN, l); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Unable to set %s: {{err}}", agentSelfRetryJoinWAN), err) + } + } + + if v, found := cfg["RetryMaxAttempts"]; found { + d.Set(agentSelfRetryMaxAttempts, int(v.(float64))) + } + + if v, found := cfg["RetryMaxAttemptsWan"]; found { + d.Set(agentSelfRetryMaxAttemptsWAN, int(v.(float64))) + } + + if v, found := cfg["SerfLanBindAddr"]; found { + d.Set(agentSelfSerfLANBindAddr, v.(string)) + } + + if v, found := cfg["SerfWanBindAddr"]; found { + d.Set(agentSelfSerfWANBindAddr, v.(string)) + } + + if v, found := cfg["Server"]; found { + d.Set(agentSelfServerMode, v.(bool)) + } + + if v, found := cfg["ServerName"]; found { + d.Set(agentSelfServerName, v.(string)) + } + + if v, found := cfg["SessionTTLMin"]; found { + dur := time.Duration(int64(v.(float64))) + d.Set(agentSelfSessionTTLMin, dur.String()) + } + + if v, found := cfg["StartJoin"]; found { + serverList := v.([]interface{}) + l := make([]interface{}, 0, len(serverList)) + l = append(l, serverList...) + if err := d.Set(agentSelfStartJoin, l); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Unable to set %s: {{err}}", agentSelfStartJoin), err) + } + } + + if v, found := cfg["StartJoinWan"]; found { + serverList := v.([]interface{}) + l := make([]interface{}, 0, len(serverList)) + l = append(l, serverList...) + if err := d.Set(agentSelfStartJoinWAN, l); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Unable to set %s: {{err}}", agentSelfStartJoinWAN), err) + } + } + + if v, found := cfg["SyslogFacility"]; found { + d.Set(agentSelfSyslogFacility, v.(string)) + } + + if v, found := cfg["CAFile"]; found { + d.Set(agentSelfTLSCAFile, v.(string)) + } + + if v, found := cfg["CertFile"]; found { + d.Set(agentSelfTLSCertFile, v.(string)) + } + + if v, found := cfg["KeyFile"]; found { + d.Set(agentSelfTLSKeyFile, v.(string)) + } + + if v, found := cfg["TLSMinVersion"]; found { + d.Set(agentSelfTLSMinVersion, v.(string)) + } + + if v, found := cfg["VerifyIncoming"]; found { + d.Set(agentSelfTLSVerifyIncoming, v.(bool)) + } + + if v, found := cfg["VerifyOutgoing"]; found { + d.Set(agentSelfTLSVerifyOutgoing, v.(bool)) + } + + if v, found := cfg["VerifyServerHostname"]; found { + d.Set(agentSelfTLSVerifyServerHostname, v.(bool)) + } + + if v, found := cfg["TaggedAddresses"]; found { + addrs := v.(map[string]interface{}) + + m := make(map[string]interface{}, len(addrs)) + + // NOTE(sean@): agentSelfTaggedAddressesLAN and agentSelfTaggedAddressesWAN + // are the only two known values that should be in this map at present, but + // in the future this value could/will expand and the schema should be + // releaxed to include both the known *{L,W}AN values as well as whatever + // else the user specifies. + for s, t := range addrs { + m[s] = t + } + + if err := d.Set(agentSelfTaggedAddresses, m); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Unable to set %s: {{err}}", agentSelfTaggedAddresses), err) + } + } + + if v, found := cfg["Telemetry"]; found { + telemetryCfg := v.(map[string]interface{}) + + m := make(map[string]interface{}, len(telemetryCfg)) + + if v, found := telemetryCfg["CirconusAPIApp"]; found { + m[agentSelfTelemetryCirconusAPIApp] = v.(string) + } + + if v, found := telemetryCfg["CirconusAPIURL"]; found { + m[agentSelfTelemetryCirconusAPIURL] = v.(string) + } + + if v, found := telemetryCfg["CirconusBrokerID"]; found { + m[agentSelfTelemetryCirconusBrokerID] = v.(string) + } + + if v, found := telemetryCfg["CirconusBrokerSelectTag"]; found { + m[agentSelfTelemetryCirconusBrokerSelectTag] = v.(string) + } + + if v, found := telemetryCfg["CirconusCheckDisplayName"]; found { + m[agentSelfTelemetryCirconusCheckDisplayName] = v.(string) + } + + if v, found := telemetryCfg["CirconusCheckID"]; found { + m[agentSelfTelemetryCirconusCheckID] = v.(string) + } + + if v, found := telemetryCfg["CirconusCheckInstanceID"]; found { + m[agentSelfTelemetryCirconusCheckInstanceID] = v.(string) + } + + if v, found := telemetryCfg["CirconusCheckSearchTag"]; found { + m[agentSelfTelemetryCirconusCheckSearchTag] = v.(string) + } + + if v, found := telemetryCfg["CirconusCheckSubmissionURL"]; found { + m[agentSelfTelemetryCirconusCheckSubmissionURL] = v.(string) + } + + if v, found := telemetryCfg["CirconusCheckTags"]; found { + m[agentSelfTelemetryCirconusCheckTags] = v.(string) + } + + if v, found := telemetryCfg["CirconusCheckForceMetricActivation"]; found { + m[agentSelfTelemetryCirconusCheckForceMetricActiation] = v.(string) + } + + if v, found := telemetryCfg["CirconusSubmissionInterval"]; found { + m[agentSelfTelemetryCirconusSubmissionInterval] = v.(string) + } + + if v, found := telemetryCfg["DisableHostname"]; found { + m[agentSelfTelemetryEnableHostname] = fmt.Sprintf("%t", !v.(bool)) + } + + if v, found := telemetryCfg["DogStatsdAddr"]; found { + m[agentSelfTelemetryDogStatsdAddr] = v.(string) + } + + if v, found := telemetryCfg["DogStatsdTags"]; found && v != nil { + m[agentSelfTelemetryDogStatsdTags] = append([]interface{}(nil), v.([]interface{})...) + } + + if v, found := telemetryCfg["StatsdAddr"]; found { + m[agentSelfTelemetryStatsdAddr] = v.(string) + } + + if v, found := telemetryCfg["StatsiteAddr"]; found { + m[agentSelfTelemetryStatsiteAddr] = v.(string) + } + + if v, found := telemetryCfg["StatsitePrefix"]; found { + m[agentSelfTelemetryStatsitePrefix] = v.(string) + } + + if err := d.Set(agentSelfTelemetry, m); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Unable to set %s: {{err}}", agentSelfTelemetry), err) + } + } + + if v, found := cfg["TranslateWanTelemetryCfg"]; found { + d.Set(agentSelfTranslateWANAddrs, v.(bool)) + } + + if v, found := cfg["UiDir"]; found { + d.Set(agentSelfUIDir, v.(string)) + } + + if v, found := cfg["UnixSockets"]; found { + socketConfig := v.(map[string]interface{}) + + m := make(map[string]interface{}, len(socketConfig)) + + if v, found := socketConfig["Grp"]; found { + m[agentSelfUnixSocketGroup] = v.(string) + } + + if v, found := socketConfig["Mode"]; found { + m[agentSelfUnixSocketMode] = v.(string) + } + + if v, found := socketConfig["Usr"]; found { + m[agentSelfUnixSocketUser] = v.(string) + } + + if err := d.Set(agentSelfUnixSockets, m); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Unable to set %s: {{err}}", agentSelfUnixSockets), err) + } + } + + if v, found := cfg["Version"]; found { + d.Set(agentSelfVersion, v.(string)) + } + + if v, found := cfg["VersionPrerelease"]; found { + d.Set(agentSelfVersionPrerelease, v.(string)) + } + + if v, found := cfg["VersionPrerelease"]; found { + d.Set(agentSelfVersionPrerelease, v.(string)) + } + + if v, found := cfg["Revision"]; found { + d.Set(agentSelfVersionRevision, v.(string)) + } + return nil } diff --git a/builtin/providers/consul/data_source_consul_agent_self_test.go b/builtin/providers/consul/data_source_consul_agent_self_test.go index b52b3f8706db..341a89c9c3b1 100644 --- a/builtin/providers/consul/data_source_consul_agent_self_test.go +++ b/builtin/providers/consul/data_source_consul_agent_self_test.go @@ -16,11 +16,52 @@ func TestAccDataConsulAgentSelf_basic(t *testing.T) { resource.TestStep{ Config: testAccDataConsulAgentSelfConfig, Check: resource.ComposeTestCheckFunc( - testAccCheckDataSourceValue("data.consul_agent_self.read", "bootstrap", "false"), - testAccCheckDataSourceValue("data.consul_agent_self.read", "datacenter", "dc1"), + testAccCheckDataSourceValue("data.consul_agent_self.read", "acl_datacenter", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "acl_default_policy", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "acl_disabled_ttl", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "acl_down_policy", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "acl_enforce_0_8_semantics", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "acl_ttl", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "advertise_addr", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "bind_addr", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "bootstrap_expect", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "bootstrap_mode", "false"), + testAccCheckDataSourceValue("data.consul_agent_self.read", "client_addr", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "datacenter", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "dev_mode", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "domain", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "enable_anonymous_signature", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "enable_coordinates", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "enable_debug", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "enable_remote_exec", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "enable_syslog", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "enable_ui", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "enable_update_check", ""), testAccCheckDataSourceValue("data.consul_agent_self.read", "id", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "leave_on_int", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "leave_on_term", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "log_level", ""), testAccCheckDataSourceValue("data.consul_agent_self.read", "name", ""), - testAccCheckDataSourceValue("data.consul_agent_self.read", "server", "true"), + testAccCheckDataSourceValue("data.consul_agent_self.read", "pid_file", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "rejoin_after_leave", ""), + // testAccCheckDataSourceValue("data.consul_agent_self.read", "retry_join", ""), + // testAccCheckDataSourceValue("data.consul_agent_self.read", "retry_join_wan", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "retry_max_attempts", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "retry_max_attempts_wan", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "serf_lan_bind_addr", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "serf_wan_bind_addr", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "server_mode", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "server_name", ""), + // testAccCheckDataSourceValue("data.consul_agent_self.read", "start_join", ""), + // testAccCheckDataSourceValue("data.consul_agent_self.read", "start_join_wan", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "syslog_facility", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "telemetry.enable_hostname", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "tls_ca_file", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "tls_cert_file", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "tls_key_file", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "tls_verify_incoming", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "tls_verify_outgoing", ""), + testAccCheckDataSourceValue("data.consul_agent_self.read", "tls_verify_server_hostname", ""), ), }, }, @@ -33,14 +74,15 @@ func testAccCheckDataSourceValue(n, attr, val string) resource.TestCheckFunc { if !ok { return fmt.Errorf("Resource not found") } - out, ok := rn.Primary.Attributes[attr] - if !ok { + out, found := rn.Primary.Attributes[attr] + switch { + case !found: return fmt.Errorf("Attribute '%s' not found: %#v", attr, rn.Primary.Attributes) - } - if val != "" && out != val { + case val == "": + // Value found, don't care what the payload is (including the zero value) + case val != "" && out != val: return fmt.Errorf("Attribute '%s' value '%s' != '%s'", attr, out, val) - } - if val == "" && out == "" { + case val == "" && out == "": return fmt.Errorf("Attribute '%s' value '%s'", attr, out) } return nil diff --git a/builtin/providers/consul/data_source_consul_catalog_nodes.go b/builtin/providers/consul/data_source_consul_catalog_nodes.go index 0565d21b1bf7..2cf440a806d7 100644 --- a/builtin/providers/consul/data_source_consul_catalog_nodes.go +++ b/builtin/providers/consul/data_source_consul_catalog_nodes.go @@ -2,7 +2,6 @@ package consul import ( "fmt" - "time" consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/errwrap" @@ -115,44 +114,9 @@ func dataSourceConsulCatalogNodesRead(d *schema.ResourceData, meta interface{}) client := meta.(*consulapi.Client) // Parse out data source filters to populate Consul's query options - - dc, err := getDC(d, client) + queryOpts, err := getQueryOpts(d, client) if err != nil { - return err - } - - queryOpts := &consulapi.QueryOptions{ - Datacenter: dc, - } - - if v, ok := d.GetOk(allowStale); ok { - queryOpts.AllowStale = v.(bool) - } - - if v, ok := d.GetOk(requireConsistent); ok { - queryOpts.RequireConsistent = v.(bool) - } - - if v, ok := d.GetOk(nodeMeta); ok { - m := v.(map[string]interface{}) - nodeMetaMap := make(map[string]string, len(nodeMeta)) - for s, t := range m { - nodeMetaMap[s] = t.(string) - } - queryOpts.NodeMeta = nodeMetaMap - } - - if v, ok := d.GetOk(token); ok { - queryOpts.Token = v.(string) - } - - if v, ok := d.GetOk(waitIndex); ok { - queryOpts.WaitIndex = uint64(v.(int)) - } - - if v, ok := d.GetOk(waitTime); ok { - d, _ := time.ParseDuration(v.(string)) - queryOpts.WaitTime = d + return errwrap.Wrapf("unable to get query options for fetching catalog nodes: {{err}}", err) } nodes, meta, err := client.Catalog().Nodes(queryOpts) @@ -199,9 +163,9 @@ func dataSourceConsulCatalogNodesRead(d *schema.ResourceData, meta interface{}) } const idKeyFmt = "catalog-nodes-%s" - d.SetId(fmt.Sprintf(idKeyFmt, dc)) + d.SetId(fmt.Sprintf(idKeyFmt, queryOpts.Datacenter)) - d.Set("datacenter", dc) + d.Set("datacenter", queryOpts.Datacenter) if err := d.Set(nodesAttr, l); err != nil { return errwrap.Wrapf("Unable to store nodes: {{err}}", err) } diff --git a/builtin/providers/consul/utils.go b/builtin/providers/consul/utils.go index ce7c764c0654..4420575627f4 100644 --- a/builtin/providers/consul/utils.go +++ b/builtin/providers/consul/utils.go @@ -1,536 +1,51 @@ package consul import ( - "bytes" - "fmt" - "sort" - "strconv" + "time" - "github.com/hashicorp/errwrap" - "github.com/hashicorp/terraform/helper/hashcode" + consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/terraform/helper/schema" ) -// apiAttr is the type used for constants representing well known keys within -// the API that are transmitted back to a resource over an API. -type apiAttr string - -// schemaAttr is the type used for constants representing well known keys -// within the schema for a resource. -type schemaAttr string - -// sourceFlags represent the ways in which an attribute can be written. Some -// sources are mutually exclusive, yet other flag combinations are composable. -type sourceFlags int - -// typeKey is the lookup mechanism for the generated schema. -type typeKey int - -const ( - // sourceUserRequired indicates the parameter must be provided by the user in - // their configuration. - sourceUserRequired sourceFlags = 1 << iota - - // sourceUserOptional indicates the parameter may optionally be specified by - // the user in their configuration. - sourceUserOptional - - // sourceAPIResult indicates the parameter may only be set by the return of - // an API call. - sourceAPIResult - - // sourceLocalFilter indicates the parameter is only used as input to the - // resource or data source and not to be entered into the state file. - sourceLocalFilter -) - -const ( - // modifyState is a mask that selects all attribute sources that can modify - // the state (i.e. everything but filters used in data sources). - modifyState = sourceUserRequired | sourceUserOptional | sourceAPIResult - - // computedAttrMask is a mask that selects source*'s that are Computed in the - // schema. - computedAttrMask = sourceAPIResult - - // optionalAttrMask is a mask that selects source*'s that are Optional in the - // schema. - optionalAttrMask = sourceAPIResult | sourceLocalFilter - - // requiredAttrMask is a mask that selects source*'s that are Required in the - // schema. - requiredAttrMask = sourceUserRequired -) - -type typeEntry struct { - APIName apiAttr - APIAliases []apiAttr - Source sourceFlags - Default interface{} - Description string - SchemaName schemaAttr - Type schema.ValueType - ValidateFuncs []interface{} - SetMembers map[typeKey]*typeEntry - ListSchema map[typeKey]*typeEntry - - // APITest, if returns true, will call APIToState. The if the value was - // found, the second return parameter will include the value that should be - // set in the state store. - APITest func(*typeEntry, interface{}) (interface{}, bool) - - // APIToState takes the value from APITest and writes it to the attrWriter - APIToState func(*typeEntry, interface{}, attrWriter) error - - // ConfigRead, if it returns true, returned a value that will be passed to its - // ConfigUse handler. - ConfigRead func(*typeEntry, attrReader) (interface{}, bool) - - // ConfigUse takes the value returned from ConfigRead as the second argument - // and a 3rd optional opaque context argument. - ConfigUse func(e *typeEntry, v interface{}, target interface{}) error -} - -type typeHandlers struct { - APITest func(*typeEntry, interface{}) (interface{}, bool) - APIToState func(*typeEntry, interface{}, attrWriter) error -} - -var typeHandlerLookupMap = map[schema.ValueType]*typeHandlers{ - schema.TypeBool: &typeHandlers{ - APITest: apiTestBool, - APIToState: apiToStateBool, - }, - schema.TypeFloat: &typeHandlers{ - APITest: apiTestFloat64, - APIToState: apiToStateFloat64, - }, - schema.TypeList: &typeHandlers{ - APITest: apiTestList, - APIToState: apiToStateList, - }, - schema.TypeMap: &typeHandlers{ - APITest: apiTestMap, - APIToState: apiToStateMap, - }, - schema.TypeSet: &typeHandlers{ - APITest: apiTestSet, - APIToState: apiToStateSet, - }, - schema.TypeString: &typeHandlers{ - APITest: apiTestString, - APIToState: apiToStateString, - }, -} - -func apiTestBool(e *typeEntry, self interface{}) (interface{}, bool) { - m := self.(map[string]interface{}) - - v, found := m[string(e.APIName)] - if found { - if b, ok := v.(bool); ok { - return b, true - } else { - panic(fmt.Sprintf("PROVIDER BUG: %q fails bool type assertion", e.SchemaName)) - } +func getQueryOpts(d *schema.ResourceData, client *consulapi.Client) (*consulapi.QueryOptions, error) { + dc, err := getDC(d, client) + if err != nil { + return nil, err } - return false, false -} - -func apiTestFloat64(e *typeEntry, self interface{}) (interface{}, bool) { - m := self.(map[string]interface{}) - - v, found := m[string(e.APIName)] - if found { - if f, ok := v.(float64); ok { - return f, true - } else { - panic(fmt.Sprintf("PROVIDER BUG: %q fails float64 type assertion", e.SchemaName)) - } + queryOpts := &consulapi.QueryOptions{ + Datacenter: dc, } - return 0.0, false -} -func apiTestID(e *typeEntry, self interface{}) (interface{}, bool) { - m := self.(map[string]interface{}) - - v, _ := apiTestString(e, m) - - // Unconditionally return true so that the call to the APIToState handler can - // return an error. - return v, true -} - -func apiTestList(e *typeEntry, self interface{}) (interface{}, bool) { - m := self.(map[string]interface{}) - - names := append([]apiAttr{e.APIName}, e.APIAliases...) - const defaultListLen = 8 - l := make([]interface{}, 0, defaultListLen) - - var foundName bool - for _, name := range names { - v, found := m[string(name)] - if found { - foundName = true - // TODO(sean@): should make a list writer that normalizes v.(type) to a - // string. For now we only accept strings and lists. - switch u := v.(type) { - case []interface{}: - l = append(l, u...) - case string: - l = append(l, u) - default: - panic(fmt.Sprintf("PROVIDER BUG: %q fails list type assertion", e.SchemaName)) - } - } + if v, ok := d.GetOk(allowStale); ok { + queryOpts.AllowStale = v.(bool) } - if foundName { - return l, true + if v, ok := d.GetOk(requireConsistent); ok { + queryOpts.RequireConsistent = v.(bool) } - return []interface{}{}, false -} - -func apiTestMap(e *typeEntry, selfRaw interface{}) (interface{}, bool) { - self := selfRaw.(map[string]interface{}) - - v, found := self[string(e.APIName)] - if found { - if m, ok := v.(map[string]interface{}); ok { - return m, true - } else { - panic(fmt.Sprintf("PROVIDER BUG: %q fails map type assertion", e.SchemaName)) + if v, ok := d.GetOk(nodeMeta); ok { + m := v.(map[string]interface{}) + nodeMetaMap := make(map[string]string, len(nodeMeta)) + for s, t := range m { + nodeMetaMap[s] = t.(string) } + queryOpts.NodeMeta = nodeMetaMap } - return "", false -} - -func apiTestSet(e *typeEntry, selfRaw interface{}) (interface{}, bool) { - self := selfRaw.(map[string]interface{}) - - v, found := self[string(e.APIName)] - if found { - if m, ok := v.(map[string]interface{}); ok { - return m, true - } else { - panic(fmt.Sprintf("PROVIDER BUG: %q fails map type assertion", e.SchemaName)) - } - } - return "", false -} - -func apiTestString(e *typeEntry, selfRaw interface{}) (interface{}, bool) { - self := selfRaw.(map[string]interface{}) - - v, found := self[string(e.APIName)] - if found { - if s, ok := v.(string); ok { - return s, true - } else { - panic(fmt.Sprintf("PROVIDER BUG: %q fails string type assertion", e.SchemaName)) - } - } - return "", false -} - -func apiToStateBool(e *typeEntry, v interface{}, w attrWriter) error { - return w.SetBool(e.SchemaName, v.(bool)) -} - -func apiToStateID(e *typeEntry, v interface{}, w attrWriter) error { - s, ok := v.(string) - if !ok || len(s) == 0 { - return fmt.Errorf("Unable to set %q's ID to an empty or non-string value: %#v", e.SchemaName, v) - } - - stateWriter, ok := w.(*attrWriterState) - if !ok { - return fmt.Errorf("PROVIDER BUG: unable to SetID with a non-attrWriterState") - } - - stateWriter.SetID(s) - - return nil -} -func apiToStateFloat64(e *typeEntry, v interface{}, w attrWriter) error { - f, ok := v.(float64) - if !ok { - return fmt.Errorf("PROVIDER BUG: unable to cast %s to a float64", e.SchemaName) + if v, ok := d.GetOk(token); ok { + queryOpts.Token = v.(string) } - return w.SetFloat64(e.SchemaName, f) -} - -func apiToStateList(e *typeEntry, v interface{}, w attrWriter) error { - l, ok := v.([]interface{}) - if !ok { - return fmt.Errorf("PROVIDER BUG: unable to cast %s to a list", e.SchemaName) - } - - return w.SetList(e.SchemaName, l) -} - -func apiToStateMap(e *typeEntry, v interface{}, w attrWriter) error { - rawMap, ok := v.(map[string]interface{}) - if !ok { - return fmt.Errorf("PROVIDER BUG: unable to cast %s to a map", e.SchemaName) - } - - mWriter := newMapWriter(make(map[string]interface{}, len(rawMap))) - - // Make a lookup map by API Schema Name - var setMembersLen int - if e.SetMembers != nil { - setMembersLen = len(e.SetMembers) - } - apiLookup := make(map[string]*typeEntry, setMembersLen) - for _, typeEntry := range e.SetMembers { - apiLookup[string(e.SchemaName)] = typeEntry + if v, ok := d.GetOk(waitIndex); ok { + queryOpts.WaitIndex = uint64(v.(int)) } - for k, v := range rawMap { - var usedSchemaHandler bool - if attrEntry, found := apiLookup[k]; found { - usedSchemaHandler = true - if err := attrEntry.APIToState(e, v, mWriter); err != nil { - return errwrap.Wrapf(fmt.Sprintf("Error calling API to state handler on %s: {{err}}", k), err) - } - } - - if !usedSchemaHandler { - if err := mWriter.Set(schemaAttr(k), v); err != nil { - return errwrap.Wrapf("Unable to store map in state: {{err}}", err) - } - } - } - - return w.SetMap(e.SchemaName, mWriter.ToMap()) -} - -func apiToStateSet(e *typeEntry, v interface{}, w attrWriter) error { - s, ok := v.([]map[string]interface{}) - if !ok { - return fmt.Errorf("PROVIDER BUG: unable to cast %s to a set", e.SchemaName) + if v, ok := d.GetOk(waitTime); ok { + d, _ := time.ParseDuration(v.(string)) + queryOpts.WaitTime = d } - set := schema.NewSet(schema.HashResource(nil), nil) - set.Add(s) - - return w.SetSet(e.SchemaName, set) -} - -func apiToStateString(e *typeEntry, v interface{}, w attrWriter) error { - s, ok := v.(string) - if !ok { - return fmt.Errorf("PROVIDER BUG: unable to cast %s to a float64", e.SchemaName) - } - - return w.SetString(e.SchemaName, s) -} - -func hashMap(in interface{}) int { - return 0 - m, ok := in.(map[string]interface{}) - if !ok { - panic(fmt.Sprintf("PROVIDER BUG: Unable to cast %#v to a map", in)) - } - - keys := make([]string, 0, len(m)) - for k, _ := range m { - keys = append(keys, k) - } - - sort.Strings(keys) - - b := &bytes.Buffer{} - const defaultHashBufSize = 4096 - b.Grow(defaultHashBufSize) - - for _, k := range keys { - v, found := m[k] - if !found { - panic("PROVIDER BUG: race condition: key should not be missing") - } - - fmt.Fprintf(b, k) - switch u := v.(type) { - case string: - fmt.Fprint(b, u) - case bool: - fmt.Fprintf(b, "%t", u) - case float64: - fmt.Fprint(b, strconv.FormatFloat(u, 'g', -1, 64)) - case int, uint: - fmt.Fprintf(b, "%d", u) - case nil: - default: - panic(fmt.Sprintf("Unsupported type %T in map hasher", v)) - } - } - - return hashcode.String(b.String()) -} - -func indirect(v interface{}) interface{} { - switch v.(type) { - case string: - return v - case *string: - p := v.(*string) - if p == nil { - return nil - } - return *p - default: - return v - } -} - -func (e *typeEntry) LookupDefaultTypeHandler() *typeHandlers { - h, found := typeHandlerLookupMap[e.Type] - if !found { - panic(fmt.Sprintf("PROVIDER BUG: unable to lookup %q's type (%#v)", e.SchemaName, e.Type)) - } - - return h -} - -func (e *typeEntry) MustLookupTypeHandler() *typeHandlers { - h := &typeHandlers{ - APITest: e.APITest, - APIToState: e.APIToState, - } - - defaultHandler := e.LookupDefaultTypeHandler() - - if h.APITest == nil { - h.APITest = defaultHandler.APITest - - if h.APITest == nil { - panic(fmt.Sprint("PROVIDER BUG: %v missing APITest method", e.SchemaName)) - } - } - - if h.APIToState == nil { - h.APIToState = defaultHandler.APIToState - - if h.APIToState == nil { - panic(fmt.Sprint("PROVIDER BUG: %v missing APIToState method", e.SchemaName)) - } - } - - return h -} - -// negateBoolToState is a factory function that creates a new function that -// negates whatever the bool is that's passed in as an argument. -func negateBoolToState(fn func(*typeEntry, interface{}, attrWriter) error) func(*typeEntry, interface{}, attrWriter) error { - return func(e *typeEntry, v interface{}, w attrWriter) error { - b, ok := v.(bool) - if !ok { - return fmt.Errorf("Unable to type assert non-bool value: %#v", v) - } - - return fn(e, !b, w) - } -} - -// stateSet sets an attribute based on an attrName. Return an error if the -// Set() to schema.ResourceData fails. -func stateSet(d *schema.ResourceData, attrName schemaAttr, v interface{}) error { - if err := d.Set(string(attrName), indirect(v)); err != nil { - return fmt.Errorf("PROVIDER BUG: failed set schema attribute %s to value %#v: %v", attrName, v, err) - } - - return nil -} - -func typeEntryListToSchema(e *typeEntry) map[string]*schema.Schema { - return map[string]*schema.Schema{ - string(e.SchemaName): e.ToSchema(), - } -} - -func typeEntryMapToResource(in map[typeKey]*typeEntry) *schema.Resource { - return &schema.Resource{ - Schema: typeEntryMapToSchema(in), - } -} - -func typeEntryMapToSchema(in map[typeKey]*typeEntry) map[string]*schema.Schema { - out := make(map[string]*schema.Schema, len(in)) - for _, e := range in { - out[string(e.SchemaName)] = e.ToSchema() - } - - return out -} - -func (e *typeEntry) Validate() { - if e.Source&sourceAPIResult != 0 && e.Type == schema.TypeSet { - panic(fmt.Sprintf("PROVIDER BUG: %s can not be computed and of type Set", e.SchemaName)) - } - - if e.Source&sourceLocalFilter != 0 { - if e.ConfigRead == nil { - panic(fmt.Sprintf("PROVIDER BUG: %s can not be configured as a local filter and be missing a config read handler", e.SchemaName)) - } - - if e.ConfigUse == nil { - panic(fmt.Sprintf("PROVIDER BUG: %s can not be configured as a local filter and be missing a config use handler", e.SchemaName)) - } - } - - if len(e.SetMembers) != 0 && !(e.Type == schema.TypeSet || e.Type == schema.TypeMap) { - panic(fmt.Sprintf("PROVIDER BUG: %s is not of type Set but has SetMembers set", e.SchemaName)) - } - - if e.Source&(sourceUserRequired|sourceAPIResult) == (sourceUserRequired | sourceAPIResult) { - panic(fmt.Sprintf("PROVIDER BUG: %#v and %#v are mutually exclusive Source flags", sourceUserRequired, sourceAPIResult)) - } -} - -func (e *typeEntry) ToSchema() *schema.Schema { - e.Validate() - - attr := &schema.Schema{ - Computed: e.Source&computedAttrMask != 0, - Default: e.Default, - Description: e.Description, - Optional: e.Source&optionalAttrMask != 0, - Required: e.Source&requiredAttrMask != 0, - Type: e.Type, - // ValidateFunc: e.MakeValidationFunc(), - } - - // Fixup the type: use the real type vs a surrogate type - switch e.Type { - case schema.TypeList: - if e.ListSchema == nil { - attr.Elem = &schema.Schema{ - Type: schema.TypeString, - } - } else { - attr.Elem = typeEntryMapToResource(e.ListSchema) - } - - case schema.TypeSet: - attr.Elem = &schema.Resource{ - Schema: typeEntryMapToSchema(e.SetMembers), - } - } - - return attr -} - -func mapStringToMapInterface(in map[string]string) map[string]interface{} { - out := make(map[string]interface{}, len(in)) - for k, v := range in { - out[k] = v - } - return out + return queryOpts, nil } diff --git a/builtin/providers/consul/validators.go b/builtin/providers/consul/validators.go index 55591cbaffb0..8e74223f1eab 100644 --- a/builtin/providers/consul/validators.go +++ b/builtin/providers/consul/validators.go @@ -3,6 +3,7 @@ package consul import ( "fmt" "regexp" + "strconv" "time" "github.com/hashicorp/errwrap" @@ -15,6 +16,9 @@ type validatorInputs []interface{} // validateDurationMin is the minimum duration to accept as input type validateDurationMin string +// validateIntMax is the maximum integer value to accept as input +type validateIntMax int + // validateIntMin is the minimum integer value to accept as input type validateIntMin int @@ -35,6 +39,8 @@ func makeValidationFunc(name string, validators []interface{}) func(v interface{ switch u := v.(type) { case validateDurationMin: fns = append(fns, validateDurationMinFactory(name, string(u))) + case validateIntMax: + fns = append(fns, validateIntMaxFactory(name, int(u))) case validateIntMin: fns = append(fns, validateIntMinFactory(name, int(u))) case validateRegexp: @@ -77,10 +83,50 @@ func validateDurationMinFactory(name, minDuration string) func(v interface{}, ke } } +func validateIntMaxFactory(name string, max int) func(v interface{}, key string) (warnings []string, errors []error) { + return func(v interface{}, key string) (warnings []string, errors []error) { + switch u := v.(type) { + case string: + i, err := strconv.ParseInt(u, 10, 64) + if err != nil { + errors = append(errors, errwrap.Wrapf(fmt.Sprintf("unable to convert %q to an integer: {{err}}", u), err)) + break + } + + if i > int64(max) { + errors = append(errors, fmt.Errorf("Invalid %s specified: %d more than the required maximum %d", name, v.(int), max)) + } + case int: + if u > max { + errors = append(errors, fmt.Errorf("Invalid %s specified: %d more than the required maximum %d", name, v.(int), max)) + } + default: + errors = append(errors, fmt.Errorf("Unsupported type in int max validation: %T", v)) + } + + return warnings, errors + } +} + func validateIntMinFactory(name string, min int) func(v interface{}, key string) (warnings []string, errors []error) { return func(v interface{}, key string) (warnings []string, errors []error) { - if v.(int) < min { - errors = append(errors, fmt.Errorf("Invalid %s specified: %d less than the required minimum %d", name, v.(int), min)) + switch u := v.(type) { + case string: + i, err := strconv.ParseInt(u, 10, 64) + if err != nil { + errors = append(errors, errwrap.Wrapf(fmt.Sprintf("unable to convert %q to an integer: {{err}}", u), err)) + break + } + + if i < int64(min) { + errors = append(errors, fmt.Errorf("Invalid %s specified: %d less than the required minimum %d", name, v.(int), min)) + } + case int: + if u < min { + errors = append(errors, fmt.Errorf("Invalid %s specified: %d less than the required minimum %d", name, v.(int), min)) + } + default: + errors = append(errors, fmt.Errorf("Unsupported type in int min validation: %T", v)) } return warnings, errors From 0d049026be33dc3a28ee2d25f1879e4215629894 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Mon, 13 Feb 2017 12:10:33 -0800 Subject: [PATCH 11/23] Remove unused helper functions. --- builtin/providers/consul/attr_reader.go | 17 --- .../providers/consul/attr_reader_config.go | 111 ------------------ builtin/providers/consul/attr_writer.go | 14 --- builtin/providers/consul/attr_writer_map.go | 70 ----------- builtin/providers/consul/attr_writer_state.go | 45 ------- 5 files changed, 257 deletions(-) delete mode 100644 builtin/providers/consul/attr_reader.go delete mode 100644 builtin/providers/consul/attr_reader_config.go delete mode 100644 builtin/providers/consul/attr_writer.go delete mode 100644 builtin/providers/consul/attr_writer_map.go delete mode 100644 builtin/providers/consul/attr_writer_state.go diff --git a/builtin/providers/consul/attr_reader.go b/builtin/providers/consul/attr_reader.go deleted file mode 100644 index fa79a69beb2f..000000000000 --- a/builtin/providers/consul/attr_reader.go +++ /dev/null @@ -1,17 +0,0 @@ -package consul - -import "time" - -type attrReader interface { - GetBool(schemaAttr) bool - GetBoolOK(schemaAttr) (b, ok bool) - GetDurationOK(schemaAttr) (time.Duration, bool) - GetFloat64OK(schemaAttr) (float64, bool) - GetIntOK(schemaAttr) (int, bool) - GetIntPtr(schemaAttr) *int - GetString(schemaAttr) string - GetStringOK(schemaAttr) (string, bool) - GetStringPtr(schemaAttr) *string - GetStringSlice(attrName schemaAttr) []string - BackingType() string -} diff --git a/builtin/providers/consul/attr_reader_config.go b/builtin/providers/consul/attr_reader_config.go deleted file mode 100644 index 66e03d9cd760..000000000000 --- a/builtin/providers/consul/attr_reader_config.go +++ /dev/null @@ -1,111 +0,0 @@ -package consul - -import ( - "time" - - "github.com/hashicorp/terraform/helper/schema" -) - -type configReader struct { - d *schema.ResourceData -} - -func newConfigReader(d *schema.ResourceData) *configReader { - return &configReader{ - d: d, - } -} - -func (r *configReader) BackingType() string { - return "config" -} - -func (r *configReader) GetBool(attrName schemaAttr) bool { - if v, ok := r.d.GetOk(string(attrName)); ok { - return v.(bool) - } - - return false -} - -func (r *configReader) GetBoolOK(attrName schemaAttr) (b, ok bool) { - if v, ok := r.d.GetOk(string(attrName)); ok { - return v.(bool), true - } - - return false, false -} - -func (r *configReader) GetDurationOK(attrName schemaAttr) (time.Duration, bool) { - if v, ok := r.d.GetOk(string(attrName)); ok { - d, err := time.ParseDuration(v.(string)) - if err != nil { - return time.Duration(0), false - } - return d, true - } - - return time.Duration(0), false -} - -func (r *configReader) GetFloat64OK(attrName schemaAttr) (float64, bool) { - if v, ok := r.d.GetOk(string(attrName)); ok { - return v.(float64), true - } - - return 0.0, false -} - -func (r *configReader) GetIntOK(attrName schemaAttr) (int, bool) { - if v, ok := r.d.GetOk(string(attrName)); ok { - return v.(int), true - } - - return 0, false -} - -func (r *configReader) GetIntPtr(attrName schemaAttr) *int { - if v, ok := r.d.GetOk(string(attrName)); ok { - i := v.(int) - return &i - } - - return nil -} - -func (r *configReader) GetString(attrName schemaAttr) string { - if v, ok := r.d.GetOk(string(attrName)); ok { - return v.(string) - } - - return "" -} - -func (r *configReader) GetStringOK(attrName schemaAttr) (string, bool) { - if v, ok := r.d.GetOk(string(attrName)); ok { - return v.(string), true - } - - return "", false -} - -func (r *configReader) GetStringPtr(attrName schemaAttr) *string { - if v, ok := r.d.GetOk(string(attrName)); ok { - switch v.(type) { - case string: - s := v.(string) - return &s - case *string: - return v.(*string) - } - } - - return nil -} - -func (r *configReader) GetStringSlice(attrName schemaAttr) []string { - if listRaw, ok := r.d.GetOk(string(attrName)); ok { - return listRaw.([]string) - } - return nil -} diff --git a/builtin/providers/consul/attr_writer.go b/builtin/providers/consul/attr_writer.go deleted file mode 100644 index c1785f6f125d..000000000000 --- a/builtin/providers/consul/attr_writer.go +++ /dev/null @@ -1,14 +0,0 @@ -package consul - -import "github.com/hashicorp/terraform/helper/schema" - -type attrWriter interface { - BackingType() string - - SetBool(schemaAttr, bool) error - SetFloat64(schemaAttr, float64) error - SetList(schemaAttr, []interface{}) error - SetMap(schemaAttr, map[string]interface{}) error - SetSet(schemaAttr, *schema.Set) error - SetString(schemaAttr, string) error -} diff --git a/builtin/providers/consul/attr_writer_map.go b/builtin/providers/consul/attr_writer_map.go deleted file mode 100644 index 071ff52a0f8a..000000000000 --- a/builtin/providers/consul/attr_writer_map.go +++ /dev/null @@ -1,70 +0,0 @@ -package consul - -import ( - "fmt" - "strconv" - - "github.com/hashicorp/terraform/helper/schema" -) - -type attrWriterMap struct { - m map[string]interface{} -} - -func newMapWriter(m map[string]interface{}) *attrWriterMap { - return &attrWriterMap{ - m: m, - } -} - -func (w *attrWriterMap) BackingType() string { - return "map" -} - -func (w *attrWriterMap) Set(name schemaAttr, v interface{}) error { - switch u := v.(type) { - case string: - return w.SetString(name, u) - case float64: - return w.SetFloat64(name, u) - case bool: - return w.SetBool(name, u) - case nil: - return w.SetString(name, "") - default: - panic(fmt.Sprintf("PROVIDER BUG: Set type %T not supported (%#v) for %s ", v, v, name)) - } -} - -func (w *attrWriterMap) SetBool(name schemaAttr, b bool) error { - w.m[string(name)] = fmt.Sprintf("%t", b) - return nil -} - -func (w *attrWriterMap) SetFloat64(name schemaAttr, f float64) error { - w.m[string(name)] = strconv.FormatFloat(f, 'g', -1, 64) - return nil -} - -func (w *attrWriterMap) SetList(name schemaAttr, l []interface{}) error { - panic(fmt.Sprintf("PROVIDER BUG: Cat set a list within a map for %s", name)) -} - -func (w *attrWriterMap) SetMap(name schemaAttr, m map[string]interface{}) error { - w.m[string(name)] = m - return nil - panic(fmt.Sprintf("PROVIDER BUG: Cat set a map within a map for %s", name)) -} - -func (w *attrWriterMap) SetSet(name schemaAttr, s *schema.Set) error { - panic(fmt.Sprintf("PROVIDER BUG: Cat set a set within a map for %s", name)) -} - -func (w *attrWriterMap) SetString(name schemaAttr, s string) error { - w.m[string(name)] = s - return nil -} - -func (w *attrWriterMap) ToMap() map[string]interface{} { - return w.m -} diff --git a/builtin/providers/consul/attr_writer_state.go b/builtin/providers/consul/attr_writer_state.go deleted file mode 100644 index 561d38d1d27e..000000000000 --- a/builtin/providers/consul/attr_writer_state.go +++ /dev/null @@ -1,45 +0,0 @@ -package consul - -import "github.com/hashicorp/terraform/helper/schema" - -type attrWriterState struct { - d *schema.ResourceData -} - -func newStateWriter(d *schema.ResourceData) *attrWriterState { - return &attrWriterState{ - d: d, - } -} - -func (w *attrWriterState) BackingType() string { - return "state" -} - -func (w *attrWriterState) SetBool(name schemaAttr, b bool) error { - return stateSet(w.d, name, b) -} - -func (w *attrWriterState) SetID(id string) { - w.d.SetId(id) -} - -func (w *attrWriterState) SetFloat64(name schemaAttr, f float64) error { - return stateSet(w.d, name, f) -} - -func (w *attrWriterState) SetList(name schemaAttr, l []interface{}) error { - return stateSet(w.d, name, l) -} - -func (w *attrWriterState) SetMap(name schemaAttr, m map[string]interface{}) error { - return stateSet(w.d, name, m) -} - -func (w *attrWriterState) SetSet(name schemaAttr, s *schema.Set) error { - return stateSet(w.d, name, []interface{}{s}) -} - -func (w *attrWriterState) SetString(name schemaAttr, s string) error { - return stateSet(w.d, name, s) -} From 974415d5cf28ef88321980928f9fa77a080737dc Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Mon, 13 Feb 2017 14:09:59 -0800 Subject: [PATCH 12/23] Move the query options schema into its own set and nested collection of attributes. This is being done in advance of supporting the services data source. --- .../data_source_consul_catalog_nodes.go | 46 ++------ .../data_source_consul_catalog_nodes_test.go | 12 ++- builtin/providers/consul/query_options.go | 100 ++++++++++++++++++ builtin/providers/consul/utils.go | 51 --------- 4 files changed, 113 insertions(+), 96 deletions(-) create mode 100644 builtin/providers/consul/query_options.go delete mode 100644 builtin/providers/consul/utils.go diff --git a/builtin/providers/consul/data_source_consul_catalog_nodes.go b/builtin/providers/consul/data_source_consul_catalog_nodes.go index 2cf440a806d7..8766a26aceb0 100644 --- a/builtin/providers/consul/data_source_consul_catalog_nodes.go +++ b/builtin/providers/consul/data_source_consul_catalog_nodes.go @@ -9,13 +9,7 @@ import ( ) const ( - allowStale = "allow_stale" - nodeMeta = "node_meta" - nodesAttr = "nodes" - requireConsistent = "require_consistent" - token = "token" - waitIndex = "wait_index" - waitTime = "wait_time" + queryOptNodesAttr = "nodes" nodeID = "id" nodeAddress = "address" @@ -23,6 +17,8 @@ const ( nodeName = "name" nodeTaggedAddresses = "tagged_addresses" + queryOpts = "query_opts" + apiTaggedLAN = "lan" apiTaggedWAN = "wan" schemaTaggedLAN = "lan" @@ -33,12 +29,8 @@ func dataSourceConsulCatalogNodes() *schema.Resource { return &schema.Resource{ Read: dataSourceConsulCatalogNodesRead, Schema: map[string]*schema.Schema{ - allowStale: &schema.Schema{ - Optional: true, - Default: true, - Type: schema.TypeBool, - }, - nodesAttr: &schema.Schema{ + queryOpts: schemaQueryOpts, + queryOptNodesAttr: &schema.Schema{ Computed: true, Type: schema.TypeList, Elem: &schema.Resource{ @@ -80,32 +72,6 @@ func dataSourceConsulCatalogNodes() *schema.Resource { }, }, }, - requireConsistent: &schema.Schema{ - Optional: true, - Default: false, - Type: schema.TypeBool, - }, - token: &schema.Schema{ - Optional: true, - Default: true, - Type: schema.TypeString, - }, - waitIndex: &schema.Schema{ - Optional: true, - Default: true, - Type: schema.TypeInt, - ValidateFunc: makeValidationFunc(waitIndex, []interface{}{ - validateIntMin(0), - }), - }, - waitTime: &schema.Schema{ - Optional: true, - Default: true, - Type: schema.TypeString, - ValidateFunc: makeValidationFunc(waitTime, []interface{}{ - validateDurationMin("0ns"), - }), - }, }, } } @@ -166,7 +132,7 @@ func dataSourceConsulCatalogNodesRead(d *schema.ResourceData, meta interface{}) d.SetId(fmt.Sprintf(idKeyFmt, queryOpts.Datacenter)) d.Set("datacenter", queryOpts.Datacenter) - if err := d.Set(nodesAttr, l); err != nil { + if err := d.Set(queryOptNodesAttr, l); err != nil { return errwrap.Wrapf("Unable to store nodes: {{err}}", err) } diff --git a/builtin/providers/consul/data_source_consul_catalog_nodes_test.go b/builtin/providers/consul/data_source_consul_catalog_nodes_test.go index d4c46f2f4269..94cea160d4bc 100644 --- a/builtin/providers/consul/data_source_consul_catalog_nodes_test.go +++ b/builtin/providers/consul/data_source_consul_catalog_nodes_test.go @@ -26,10 +26,12 @@ func TestAccDataConsulCatalogNodes_basic(t *testing.T) { const testAccDataConsulCatalogNodesConfig = ` data "consul_catalog_nodes" "read" { - allow_stale = true - require_consistent = false - token = "" - wait_index = 0 - wait_time = "1m" + query_options { + allow_stale = true + require_consistent = false + token = "" + wait_index = 0 + wait_time = "1m" + } } ` diff --git a/builtin/providers/consul/query_options.go b/builtin/providers/consul/query_options.go new file mode 100644 index 000000000000..4598a5d828d9 --- /dev/null +++ b/builtin/providers/consul/query_options.go @@ -0,0 +1,100 @@ +package consul + +import ( + "time" + + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/terraform/helper/schema" +) + +const ( + queryOptAllowStale = "allow_stale" + queryOptNodeMeta = "node_meta" + queryOptRequireConsistent = "require_consistent" + queryOptToken = "token" + queryOptWaitIndex = "wait_index" + queryOptWaitTime = "wait_time" +) + +var schemaQueryOpts = &schema.Schema{ + Optional: true, + Type: schema.TypeSet, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + queryOptAllowStale: &schema.Schema{ + Optional: true, + Default: true, + Type: schema.TypeBool, + }, + queryOptRequireConsistent: &schema.Schema{ + Optional: true, + Default: false, + Type: schema.TypeBool, + }, + queryOptToken: &schema.Schema{ + Optional: true, + Default: true, + Type: schema.TypeString, + }, + queryOptWaitIndex: &schema.Schema{ + Optional: true, + Default: true, + Type: schema.TypeInt, + ValidateFunc: makeValidationFunc(queryOptWaitIndex, []interface{}{ + validateIntMin(0), + }), + }, + queryOptWaitTime: &schema.Schema{ + Optional: true, + Default: true, + Type: schema.TypeString, + ValidateFunc: makeValidationFunc(queryOptWaitTime, []interface{}{ + validateDurationMin("0ns"), + }), + }, + }, + }, +} + +func getQueryOpts(d *schema.ResourceData, client *consulapi.Client) (*consulapi.QueryOptions, error) { + dc, err := getDC(d, client) + if err != nil { + return nil, err + } + + queryOpts := &consulapi.QueryOptions{ + Datacenter: dc, + } + + if v, ok := d.GetOk(queryOptAllowStale); ok { + queryOpts.AllowStale = v.(bool) + } + + if v, ok := d.GetOk(queryOptRequireConsistent); ok { + queryOpts.RequireConsistent = v.(bool) + } + + if v, ok := d.GetOk(queryOptNodeMeta); ok { + m := v.(map[string]interface{}) + nodeMetaMap := make(map[string]string, len(queryOptNodeMeta)) + for s, t := range m { + nodeMetaMap[s] = t.(string) + } + queryOpts.NodeMeta = nodeMetaMap + } + + if v, ok := d.GetOk(queryOptToken); ok { + queryOpts.Token = v.(string) + } + + if v, ok := d.GetOk(queryOptWaitIndex); ok { + queryOpts.WaitIndex = uint64(v.(int)) + } + + if v, ok := d.GetOk(queryOptWaitTime); ok { + d, _ := time.ParseDuration(v.(string)) + queryOpts.WaitTime = d + } + + return queryOpts, nil +} diff --git a/builtin/providers/consul/utils.go b/builtin/providers/consul/utils.go deleted file mode 100644 index 4420575627f4..000000000000 --- a/builtin/providers/consul/utils.go +++ /dev/null @@ -1,51 +0,0 @@ -package consul - -import ( - "time" - - consulapi "github.com/hashicorp/consul/api" - "github.com/hashicorp/terraform/helper/schema" -) - -func getQueryOpts(d *schema.ResourceData, client *consulapi.Client) (*consulapi.QueryOptions, error) { - dc, err := getDC(d, client) - if err != nil { - return nil, err - } - - queryOpts := &consulapi.QueryOptions{ - Datacenter: dc, - } - - if v, ok := d.GetOk(allowStale); ok { - queryOpts.AllowStale = v.(bool) - } - - if v, ok := d.GetOk(requireConsistent); ok { - queryOpts.RequireConsistent = v.(bool) - } - - if v, ok := d.GetOk(nodeMeta); ok { - m := v.(map[string]interface{}) - nodeMetaMap := make(map[string]string, len(nodeMeta)) - for s, t := range m { - nodeMetaMap[s] = t.(string) - } - queryOpts.NodeMeta = nodeMetaMap - } - - if v, ok := d.GetOk(token); ok { - queryOpts.Token = v.(string) - } - - if v, ok := d.GetOk(waitIndex); ok { - queryOpts.WaitIndex = uint64(v.(int)) - } - - if v, ok := d.GetOk(waitTime); ok { - d, _ := time.ParseDuration(v.(string)) - queryOpts.WaitTime = d - } - - return queryOpts, nil -} From 41e42087770484cdc993217059a920fb54edee12 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Mon, 13 Feb 2017 15:00:20 -0800 Subject: [PATCH 13/23] Commit miss: `s/query_opts/query_options/` --- builtin/providers/consul/data_source_consul_catalog_nodes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/providers/consul/data_source_consul_catalog_nodes.go b/builtin/providers/consul/data_source_consul_catalog_nodes.go index 8766a26aceb0..21783d7cc8b2 100644 --- a/builtin/providers/consul/data_source_consul_catalog_nodes.go +++ b/builtin/providers/consul/data_source_consul_catalog_nodes.go @@ -17,7 +17,7 @@ const ( nodeName = "name" nodeTaggedAddresses = "tagged_addresses" - queryOpts = "query_opts" + queryOpts = "query_options" apiTaggedLAN = "lan" apiTaggedWAN = "wan" From 59925478c3d88163954e39b015666d52daab8ae4 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Tue, 14 Feb 2017 17:39:25 -0800 Subject: [PATCH 14/23] Add a `consul_catalog_service` resource to obtain detailed information about a specific Consul service. --- .../data_source_consul_catalog_service.go | 209 ++++++++++++++++++ ...data_source_consul_catalog_service_test.go | 50 +++++ builtin/providers/consul/query_options.go | 39 +++- builtin/providers/consul/resource_provider.go | 7 +- 4 files changed, 295 insertions(+), 10 deletions(-) create mode 100644 builtin/providers/consul/data_source_consul_catalog_service.go create mode 100644 builtin/providers/consul/data_source_consul_catalog_service_test.go diff --git a/builtin/providers/consul/data_source_consul_catalog_service.go b/builtin/providers/consul/data_source_consul_catalog_service.go new file mode 100644 index 000000000000..3a05fe20a22d --- /dev/null +++ b/builtin/providers/consul/data_source_consul_catalog_service.go @@ -0,0 +1,209 @@ +package consul + +import ( + "fmt" + + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform/helper/schema" + "github.com/y0ssar1an/q" +) + +const ( + queryOptServicesAttr = "services" + + catalogServiceCreateIndex = "create_index" + catalogServiceDatacenter = "datacenter" + catalogServiceModifyIndex = "modify_index" + catalogServiceNodeAddress = "node_address" + catalogServiceNodeID = "node_id" + catalogServiceNodeMeta = "node_meta" + catalogServiceNodeName = "node_name" + catalogServiceServiceAddress = "address" + catalogServiceServiceEnableTagOverride = "enable_tag_override" + catalogServiceServiceID = "id" + catalogServiceServiceName = "name" + catalogServiceServicePort = "port" + catalogServiceServiceTags = "tags" + catalogServiceTaggedAddresses = "tagged_addresses" + + // Filters + catalogServiceName = "name" + catalogServiceTag = "tag" +) + +func dataSourceConsulCatalogService() *schema.Resource { + return &schema.Resource{ + Read: dataSourceConsulCatalogServiceRead, + Schema: map[string]*schema.Schema{ + // Data Source Predicate(s) + catalogServiceDatacenter: &schema.Schema{ + // Used in the query, must be stored and force a refresh if the value changes. + Computed: true, + Type: schema.TypeString, + ForceNew: true, + }, + catalogServiceTag: &schema.Schema{ + // Used in the query, must be stored and force a refresh if the value changes. + Computed: true, + Type: schema.TypeString, + ForceNew: true, + }, + catalogServiceName: &schema.Schema{ + Required: true, + Type: schema.TypeString, + }, + queryOpts: schemaQueryOpts, + + // Out parameters + queryOptServicesAttr: &schema.Schema{ + Computed: true, + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + catalogServiceCreateIndex: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + catalogServiceNodeAddress: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + catalogServiceNodeID: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + catalogServiceModifyIndex: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + catalogServiceNodeName: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + catalogServiceNodeMeta: &schema.Schema{ + Type: schema.TypeMap, + Computed: true, + }, + catalogServiceServiceAddress: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + catalogServiceServiceEnableTagOverride: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + catalogServiceServiceID: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + catalogServiceServiceName: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + catalogServiceServicePort: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + catalogServiceServiceTags: &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + catalogServiceTaggedAddresses: &schema.Schema{ + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + schemaTaggedLAN: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + schemaTaggedWAN: &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceConsulCatalogServiceRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*consulapi.Client) + + // Parse out data source filters to populate Consul's query options + queryOpts, err := getQueryOpts(d, client) + if err != nil { + return errwrap.Wrapf("unable to get query options for fetching catalog services: {{err}}", err) + } + + var serviceName string + if v, ok := d.GetOk(catalogServiceName); ok { + serviceName = v.(string) + } + + var serviceTag string + if v, ok := d.GetOk(catalogServiceTag); ok { + serviceTag = v.(string) + } + + // services, meta, err := client.Catalog().Services(queryOpts) + services, meta, err := client.Catalog().Service(serviceName, serviceTag, queryOpts) + if err != nil { + return err + } + + l := make([]interface{}, 0, len(services)) + + q.Q(services) + for _, service := range services { + q.Q(service) + + const defaultServiceAttrs = 13 + m := make(map[string]interface{}, defaultServiceAttrs) + + m[catalogServiceCreateIndex] = fmt.Sprintf("%d", service.CreateIndex) + m[catalogServiceModifyIndex] = fmt.Sprintf("%d", service.ModifyIndex) + m[catalogServiceNodeAddress] = service.Address + m[catalogServiceNodeID] = service.ID + m[catalogServiceNodeMeta] = service.NodeMeta + m[catalogServiceNodeName] = service.Node + m[catalogServiceServiceAddress] = service.ServiceAddress + m[catalogServiceServiceEnableTagOverride] = fmt.Sprintf("%t", service.ServiceEnableTagOverride) + m[catalogServiceServiceID] = service.ServiceID + m[catalogServiceServiceName] = service.ServiceName + m[catalogServiceServicePort] = fmt.Sprintf("%d", service.ServicePort) + m[catalogServiceServiceTags] = service.ServiceTags + m[catalogServiceTaggedAddresses] = service.TaggedAddresses + + { + const initNumTaggedAddrs = 2 + taggedAddrs := make(map[string]interface{}, initNumTaggedAddrs) + if addr, found := service.TaggedAddresses[apiTaggedLAN]; found { + taggedAddrs[schemaTaggedLAN] = addr + } + if addr, found := service.TaggedAddresses[apiTaggedWAN]; found { + taggedAddrs[schemaTaggedWAN] = addr + } + m[catalogServiceTaggedAddresses] = taggedAddrs + } + + l = append(l, m) + } + + const idKeyFmt = "catalog-service-%s-%q-%q" + d.SetId(fmt.Sprintf(idKeyFmt, queryOpts.Datacenter, serviceName, serviceTag)) + + d.Set(catalogServiceDatacenter, queryOpts.Datacenter) + d.Set(catalogServiceTag, serviceTag) + if err := d.Set(queryOptServicesAttr, l); err != nil { + return errwrap.Wrapf("Unable to store services: {{err}}", err) + } + + return nil +} diff --git a/builtin/providers/consul/data_source_consul_catalog_service_test.go b/builtin/providers/consul/data_source_consul_catalog_service_test.go new file mode 100644 index 000000000000..6c214496b739 --- /dev/null +++ b/builtin/providers/consul/data_source_consul_catalog_service_test.go @@ -0,0 +1,50 @@ +package consul + +import ( + "testing" + + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccDataConsulCatalogService_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccDataConsulCatalogServiceConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckDataSourceValue("data.consul_catalog_service.read", "datacenter", "dc1"), + testAccCheckDataSourceValue("data.consul_catalog_service.read", "services.#", "1"), + testAccCheckDataSourceValue("data.consul_catalog_service.read", "services.0.address", ""), + testAccCheckDataSourceValue("data.consul_catalog_service.read", "services.0.create_index", ""), + testAccCheckDataSourceValue("data.consul_catalog_service.read", "services.0.enable_tag_override", ""), + testAccCheckDataSourceValue("data.consul_catalog_service.read", "services.0.id", ""), + testAccCheckDataSourceValue("data.consul_catalog_service.read", "services.0.modify_index", ""), + testAccCheckDataSourceValue("data.consul_catalog_service.read", "services.0.name", ""), + testAccCheckDataSourceValue("data.consul_catalog_service.read", "services.0.node_address", ""), + testAccCheckDataSourceValue("data.consul_catalog_service.read", "services.0.node_id", ""), + testAccCheckDataSourceValue("data.consul_catalog_service.read", "services.0.node_meta.%", "0"), + testAccCheckDataSourceValue("data.consul_catalog_service.read", "services.0.node_name", ""), + testAccCheckDataSourceValue("data.consul_catalog_service.read", "services.0.port", ""), + testAccCheckDataSourceValue("data.consul_catalog_service.read", "services.0.tagged_addresses.%", "2"), + testAccCheckDataSourceValue("data.consul_catalog_service.read", "services.0.tags.#", "0"), + ), + }, + }, + }) +} + +const testAccDataConsulCatalogServiceConfig = ` +data "consul_catalog_service" "read" { + query_options { + allow_stale = true + require_consistent = false + token = "" + wait_index = 0 + wait_time = "1m" + } + + name = "consul" +} +` diff --git a/builtin/providers/consul/query_options.go b/builtin/providers/consul/query_options.go index 4598a5d828d9..41348fba50e4 100644 --- a/builtin/providers/consul/query_options.go +++ b/builtin/providers/consul/query_options.go @@ -9,6 +9,8 @@ import ( const ( queryOptAllowStale = "allow_stale" + queryOptDatacenter = "datacenter" + queryOptNear = "near" queryOptNodeMeta = "node_meta" queryOptRequireConsistent = "require_consistent" queryOptToken = "token" @@ -26,6 +28,20 @@ var schemaQueryOpts = &schema.Schema{ Default: true, Type: schema.TypeBool, }, + queryOptDatacenter: &schema.Schema{ + // Optional because we'll pull the default from the local agent if it's + // not specified, but we can query remote data centers as a result. + Optional: true, + Type: schema.TypeString, + }, + queryOptNear: &schema.Schema{ + Optional: true, + Type: schema.TypeString, + }, + queryOptNodeMeta: &schema.Schema{ + Optional: true, + Type: schema.TypeMap, + }, queryOptRequireConsistent: &schema.Schema{ Optional: true, Default: false, @@ -57,17 +73,26 @@ var schemaQueryOpts = &schema.Schema{ } func getQueryOpts(d *schema.ResourceData, client *consulapi.Client) (*consulapi.QueryOptions, error) { - dc, err := getDC(d, client) - if err != nil { - return nil, err + queryOpts := &consulapi.QueryOptions{} + + if v, ok := d.GetOk(queryOptAllowStale); ok { + queryOpts.AllowStale = v.(bool) } - queryOpts := &consulapi.QueryOptions{ - Datacenter: dc, + if v, ok := d.GetOk(queryOptDatacenter); ok { + queryOpts.Datacenter = v.(string) } - if v, ok := d.GetOk(queryOptAllowStale); ok { - queryOpts.AllowStale = v.(bool) + if queryOpts.Datacenter == "" { + dc, err := getDC(d, client) + if err != nil { + return nil, err + } + queryOpts.Datacenter = dc + } + + if v, ok := d.GetOk(queryOptNear); ok { + queryOpts.Near = v.(string) } if v, ok := d.GetOk(queryOptRequireConsistent); ok { diff --git a/builtin/providers/consul/resource_provider.go b/builtin/providers/consul/resource_provider.go index 749223c5d6b0..635883d82000 100644 --- a/builtin/providers/consul/resource_provider.go +++ b/builtin/providers/consul/resource_provider.go @@ -64,9 +64,10 @@ func Provider() terraform.ResourceProvider { }, DataSourcesMap: map[string]*schema.Resource{ - "consul_agent_self": dataSourceConsulAgentSelf(), - "consul_catalog_nodes": dataSourceConsulCatalogNodes(), - "consul_keys": dataSourceConsulKeys(), + "consul_agent_self": dataSourceConsulAgentSelf(), + "consul_catalog_nodes": dataSourceConsulCatalogNodes(), + "consul_catalog_service": dataSourceConsulCatalogService(), + "consul_keys": dataSourceConsulKeys(), }, ResourcesMap: map[string]*schema.Resource{ From 4003c47c71128e1b6a5ebe27954ddd304bf06936 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Tue, 14 Feb 2017 22:11:19 -0800 Subject: [PATCH 15/23] Remove some accidentally leaked `q.Q()` calls from earlier debugging.x --- .../providers/consul/data_source_consul_catalog_service.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/builtin/providers/consul/data_source_consul_catalog_service.go b/builtin/providers/consul/data_source_consul_catalog_service.go index 3a05fe20a22d..6408fca3404e 100644 --- a/builtin/providers/consul/data_source_consul_catalog_service.go +++ b/builtin/providers/consul/data_source_consul_catalog_service.go @@ -6,7 +6,6 @@ import ( consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/errwrap" "github.com/hashicorp/terraform/helper/schema" - "github.com/y0ssar1an/q" ) const ( @@ -160,10 +159,7 @@ func dataSourceConsulCatalogServiceRead(d *schema.ResourceData, meta interface{} l := make([]interface{}, 0, len(services)) - q.Q(services) for _, service := range services { - q.Q(service) - const defaultServiceAttrs = 13 m := make(map[string]interface{}, defaultServiceAttrs) From b7c9dedf4ee4949af7ff09a3e6169bee3c5c748e Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Tue, 14 Feb 2017 23:14:58 -0800 Subject: [PATCH 16/23] Add a `consul_catalog_services` resource that enumerates the list of services in a given Consul datacenter. --- .../data_source_consul_catalog_service.go | 13 +-- .../data_source_consul_catalog_services.go | 90 +++++++++++++++++++ ...ata_source_consul_catalog_services_test.go | 36 ++++++++ builtin/providers/consul/resource_provider.go | 9 +- 4 files changed, 138 insertions(+), 10 deletions(-) create mode 100644 builtin/providers/consul/data_source_consul_catalog_services.go create mode 100644 builtin/providers/consul/data_source_consul_catalog_services_test.go diff --git a/builtin/providers/consul/data_source_consul_catalog_service.go b/builtin/providers/consul/data_source_consul_catalog_service.go index 6408fca3404e..7f41b66a3279 100644 --- a/builtin/providers/consul/data_source_consul_catalog_service.go +++ b/builtin/providers/consul/data_source_consul_catalog_service.go @@ -9,7 +9,7 @@ import ( ) const ( - queryOptServicesAttr = "services" + catalogServiceElem = "services" catalogServiceCreateIndex = "create_index" catalogServiceDatacenter = "datacenter" @@ -37,13 +37,15 @@ func dataSourceConsulCatalogService() *schema.Resource { Schema: map[string]*schema.Schema{ // Data Source Predicate(s) catalogServiceDatacenter: &schema.Schema{ - // Used in the query, must be stored and force a refresh if the value changes. + // Used in the query, must be stored and force a refresh if the value + // changes. Computed: true, Type: schema.TypeString, ForceNew: true, }, catalogServiceTag: &schema.Schema{ - // Used in the query, must be stored and force a refresh if the value changes. + // Used in the query, must be stored and force a refresh if the value + // changes. Computed: true, Type: schema.TypeString, ForceNew: true, @@ -55,7 +57,7 @@ func dataSourceConsulCatalogService() *schema.Resource { queryOpts: schemaQueryOpts, // Out parameters - queryOptServicesAttr: &schema.Schema{ + catalogServiceElem: &schema.Schema{ Computed: true, Type: schema.TypeList, Elem: &schema.Resource{ @@ -158,7 +160,6 @@ func dataSourceConsulCatalogServiceRead(d *schema.ResourceData, meta interface{} } l := make([]interface{}, 0, len(services)) - for _, service := range services { const defaultServiceAttrs = 13 m := make(map[string]interface{}, defaultServiceAttrs) @@ -197,7 +198,7 @@ func dataSourceConsulCatalogServiceRead(d *schema.ResourceData, meta interface{} d.Set(catalogServiceDatacenter, queryOpts.Datacenter) d.Set(catalogServiceTag, serviceTag) - if err := d.Set(queryOptServicesAttr, l); err != nil { + if err := d.Set(catalogServiceElem, l); err != nil { return errwrap.Wrapf("Unable to store services: {{err}}", err) } diff --git a/builtin/providers/consul/data_source_consul_catalog_services.go b/builtin/providers/consul/data_source_consul_catalog_services.go new file mode 100644 index 000000000000..dd4e7bedc59e --- /dev/null +++ b/builtin/providers/consul/data_source_consul_catalog_services.go @@ -0,0 +1,90 @@ +package consul + +import ( + "fmt" + "sort" + "strings" + + consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform/helper/schema" +) + +const ( + catalogServicesDatacenter = "datacenter" + catalogServicesNames = "names" + + catalogServicesServiceName = "name" + catalogServicesServiceTags = "tags" +) + +func dataSourceConsulCatalogServices() *schema.Resource { + return &schema.Resource{ + Read: dataSourceConsulCatalogServicesRead, + Schema: map[string]*schema.Schema{ + // Data Source Predicate(s) + catalogServicesDatacenter: &schema.Schema{ + // Used in the query, must be stored and force a refresh if the value + // changes. + Computed: true, + Type: schema.TypeString, + ForceNew: true, + }, + queryOpts: schemaQueryOpts, + + // Out parameters + catalogServicesNames: &schema.Schema{ + Computed: true, + Type: schema.TypeMap, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + catalogServiceServiceTags: &schema.Schema{ + // FIXME(sean@): Tags is currently a space separated list of tags. + // The ideal structure should be map[string][]string instead. + // When this is supported in the future this should be changed to + // be a TypeList instead. + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceConsulCatalogServicesRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*consulapi.Client) + + // Parse out data source filters to populate Consul's query options + queryOpts, err := getQueryOpts(d, client) + if err != nil { + return errwrap.Wrapf("unable to get query options for fetching catalog services: {{err}}", err) + } + + services, meta, err := client.Catalog().Services(queryOpts) + if err != nil { + return err + } + + m := make(map[string]interface{}, len(services)) + for name, tags := range services { + tagList := make([]string, 0, len(tags)) + for _, tag := range tags { + tagList = append(tagList, tag) + } + + sort.Strings(tagList) + m[name] = strings.Join(tagList, " ") + } + + const idKeyFmt = "catalog-services-%s" + d.SetId(fmt.Sprintf(idKeyFmt, queryOpts.Datacenter)) + + d.Set(catalogServicesDatacenter, queryOpts.Datacenter) + if err := d.Set(catalogServicesNames, m); err != nil { + return errwrap.Wrapf("Unable to store services: {{err}}", err) + } + + return nil +} diff --git a/builtin/providers/consul/data_source_consul_catalog_services_test.go b/builtin/providers/consul/data_source_consul_catalog_services_test.go new file mode 100644 index 000000000000..661a9b96b11c --- /dev/null +++ b/builtin/providers/consul/data_source_consul_catalog_services_test.go @@ -0,0 +1,36 @@ +package consul + +import ( + "testing" + + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccDataConsulCatalogServices_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccDataConsulCatalogServicesConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckDataSourceValue("data.consul_catalog_services.read", "datacenter", "dc1"), + testAccCheckDataSourceValue("data.consul_catalog_services.read", "names.%", "1"), + testAccCheckDataSourceValue("data.consul_catalog_services.read", "names.consul", ""), + ), + }, + }, + }) +} + +const testAccDataConsulCatalogServicesConfig = ` +data "consul_catalog_services" "read" { + query_options { + allow_stale = true + require_consistent = false + token = "" + wait_index = 0 + wait_time = "1m" + } +} +` diff --git a/builtin/providers/consul/resource_provider.go b/builtin/providers/consul/resource_provider.go index 635883d82000..fb316adccf91 100644 --- a/builtin/providers/consul/resource_provider.go +++ b/builtin/providers/consul/resource_provider.go @@ -64,10 +64,11 @@ func Provider() terraform.ResourceProvider { }, DataSourcesMap: map[string]*schema.Resource{ - "consul_agent_self": dataSourceConsulAgentSelf(), - "consul_catalog_nodes": dataSourceConsulCatalogNodes(), - "consul_catalog_service": dataSourceConsulCatalogService(), - "consul_keys": dataSourceConsulKeys(), + "consul_agent_self": dataSourceConsulAgentSelf(), + "consul_catalog_nodes": dataSourceConsulCatalogNodes(), + "consul_catalog_service": dataSourceConsulCatalogService(), + "consul_catalog_services": dataSourceConsulCatalogServices(), + "consul_keys": dataSourceConsulKeys(), }, ResourcesMap: map[string]*schema.Resource{ From 9d06a47069ab981d31b7627328b2f94af9b78d52 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Wed, 15 Feb 2017 10:57:09 -0800 Subject: [PATCH 17/23] Add docs for the `consul_catalog_services` data source. --- .../data_source_consul_catalog_services.go | 36 ++++++--- ...ata_source_consul_catalog_services_test.go | 4 +- .../providers/consul/d/services.html.markdown | 80 +++++++++++++++++++ website/source/layouts/consul.erb | 11 ++- 4 files changed, 114 insertions(+), 17 deletions(-) create mode 100644 website/source/docs/providers/consul/d/services.html.markdown diff --git a/builtin/providers/consul/data_source_consul_catalog_services.go b/builtin/providers/consul/data_source_consul_catalog_services.go index dd4e7bedc59e..ad7535a09a9c 100644 --- a/builtin/providers/consul/data_source_consul_catalog_services.go +++ b/builtin/providers/consul/data_source_consul_catalog_services.go @@ -11,10 +11,13 @@ import ( ) const ( - catalogServicesDatacenter = "datacenter" - catalogServicesNames = "names" - + // Datasource predicates catalogServicesServiceName = "name" + + // Out parameters + catalogServicesDatacenter = "datacenter" + catalogServicesNames = "names" + catalogServicesServices = "services" catalogServicesServiceTags = "tags" ) @@ -34,17 +37,19 @@ func dataSourceConsulCatalogServices() *schema.Resource { // Out parameters catalogServicesNames: &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + catalogServicesServices: &schema.Schema{ Computed: true, Type: schema.TypeMap, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ catalogServiceServiceTags: &schema.Schema{ - // FIXME(sean@): Tags is currently a space separated list of tags. - // The ideal structure should be map[string][]string instead. - // When this is supported in the future this should be changed to - // be a TypeList instead. - Type: schema.TypeString, + Type: schema.TypeList, Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, }, }, }, @@ -67,7 +72,7 @@ func dataSourceConsulCatalogServicesRead(d *schema.ResourceData, meta interface{ return err } - m := make(map[string]interface{}, len(services)) + catalogServices := make(map[string]interface{}, len(services)) for name, tags := range services { tagList := make([]string, 0, len(tags)) for _, tag := range tags { @@ -75,16 +80,25 @@ func dataSourceConsulCatalogServicesRead(d *schema.ResourceData, meta interface{ } sort.Strings(tagList) - m[name] = strings.Join(tagList, " ") + catalogServices[name] = strings.Join(tagList, " ") + } + + serviceNames := make([]interface{}, 0, len(services)) + for k := range catalogServices { + serviceNames = append(serviceNames, k) } const idKeyFmt = "catalog-services-%s" d.SetId(fmt.Sprintf(idKeyFmt, queryOpts.Datacenter)) d.Set(catalogServicesDatacenter, queryOpts.Datacenter) - if err := d.Set(catalogServicesNames, m); err != nil { + if err := d.Set(catalogServicesServices, catalogServices); err != nil { return errwrap.Wrapf("Unable to store services: {{err}}", err) } + if err := d.Set(catalogServicesNames, serviceNames); err != nil { + return errwrap.Wrapf("Unable to store service names: {{err}}", err) + } + return nil } diff --git a/builtin/providers/consul/data_source_consul_catalog_services_test.go b/builtin/providers/consul/data_source_consul_catalog_services_test.go index 661a9b96b11c..1087073f7d54 100644 --- a/builtin/providers/consul/data_source_consul_catalog_services_test.go +++ b/builtin/providers/consul/data_source_consul_catalog_services_test.go @@ -15,8 +15,8 @@ func TestAccDataConsulCatalogServices_basic(t *testing.T) { Config: testAccDataConsulCatalogServicesConfig, Check: resource.ComposeTestCheckFunc( testAccCheckDataSourceValue("data.consul_catalog_services.read", "datacenter", "dc1"), - testAccCheckDataSourceValue("data.consul_catalog_services.read", "names.%", "1"), - testAccCheckDataSourceValue("data.consul_catalog_services.read", "names.consul", ""), + testAccCheckDataSourceValue("data.consul_catalog_services.read", "services.%", "1"), + testAccCheckDataSourceValue("data.consul_catalog_services.read", "services.consul", ""), ), }, }, diff --git a/website/source/docs/providers/consul/d/services.html.markdown b/website/source/docs/providers/consul/d/services.html.markdown new file mode 100644 index 000000000000..f8fe6ee474b5 --- /dev/null +++ b/website/source/docs/providers/consul/d/services.html.markdown @@ -0,0 +1,80 @@ +--- +layout: "consul" +page_title: "Consul: consul_catalog_services" +sidebar_current: "docs-consul-data-source-catalog-services" +description: |- + Provides a list of services in a given Consul datacenter. +--- + +# consul\_catalog\_services + +The `consul_catalog_services` data source returns a list of Consul services that +have been registered with the Consul cluster in a given datacenter. By +specifying a different datacenter in the `query_options` it is possible to +retrieve a list of services from a different WAN-attached Consul datacenter. + +This data source is different from the `consul_catalog_service` (singular) data +source, which provides a detailed response about a specific Consul service. + +## Example Usage + +``` +data "consul_catalog_services" "read-dc1" { + query_options { + # Optional parameter + datacenter = "dc1" + } +} + +# Set the description to a whitespace delimited list of the services +resource "example_resource" "app" { + description = "${join(" ", data.consul_catalog_services.names)}" + ... +} +``` + +## Argument Reference + +The following arguments are supported: + +* `datacenter` - (Optional) The Consul datacenter to query. Defaults to the + same value found in `query_options` parameter specified below, or if that is + empty, the `datacenter` value found in the Consul agent that this provider is + configured to talk to. + +* `query_options` - (Optional) See below. + +The `query_options` block supports the following: + +* `allow_stale` - (Optional) When `true`, the default, allow responses from + Consul servers that are followers. + +* `require_consistent` - (Optional) When `true` force the client to perform a + read on at least quorum servers and verify the result is the same. Defaults + to `false`. + +* `token` - (Optional) Specify the Consul ACL token to use when performing the + request. This defaults to the same API token configured by the `consul` + provider but may be overriden if necessary. + +* `wait_index` - (Optional) Index number used to enable blocking quereis. + +* `wait_time` - (Optional) Max time the client should wait for a blocking query + to return. + +## Attributes Reference + +The following attributes are exported: + +* `datacenter` - The datacenter the keys are being read from to. +* `names` - A list of the Consul services found. This will always contain the + list of services found. +* `services.` - For each name given, the corresponding attribute is a + Terraform map of services and their tags. The value is an alphanumerically + sorted, whitespace delimited set of tags associated with the service. As + shown in the example above, to create a list of the available servies, wrap + the `names` attribute in a call to `keys()`. +* `tags` - A map of the tags found for each service. If more than one service + shares the same tag, unique service names will be joined by whitespace (this + is the inverse of `services` and can be used to lookup the services that match + a single tag). diff --git a/website/source/layouts/consul.erb b/website/source/layouts/consul.erb index df831b0587b9..32e0efa1d130 100644 --- a/website/source/layouts/consul.erb +++ b/website/source/layouts/consul.erb @@ -13,10 +13,13 @@ > Data Sources + > + consul_catalog_services + + > + consul_keys + + > From 1c7a9242583a984aa525754846be41951c4f4a92 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Wed, 15 Feb 2017 13:30:10 -0800 Subject: [PATCH 18/23] Update and provide docs to the `consul_catalog_service` data source. --- .../data_source_consul_catalog_service.go | 26 ++-- builtin/providers/consul/query_options.go | 3 - .../providers/consul/d/service.html.markdown | 112 ++++++++++++++++++ website/source/layouts/consul.erb | 3 + 4 files changed, 126 insertions(+), 18 deletions(-) create mode 100644 website/source/docs/providers/consul/d/service.html.markdown diff --git a/builtin/providers/consul/data_source_consul_catalog_service.go b/builtin/providers/consul/data_source_consul_catalog_service.go index 7f41b66a3279..71dc00780bb5 100644 --- a/builtin/providers/consul/data_source_consul_catalog_service.go +++ b/builtin/providers/consul/data_source_consul_catalog_service.go @@ -2,6 +2,7 @@ package consul import ( "fmt" + "sort" consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/errwrap" @@ -9,7 +10,7 @@ import ( ) const ( - catalogServiceElem = "services" + catalogServiceElem = "service" catalogServiceCreateIndex = "create_index" catalogServiceDatacenter = "datacenter" @@ -170,26 +171,20 @@ func dataSourceConsulCatalogServiceRead(d *schema.ResourceData, meta interface{} m[catalogServiceNodeID] = service.ID m[catalogServiceNodeMeta] = service.NodeMeta m[catalogServiceNodeName] = service.Node - m[catalogServiceServiceAddress] = service.ServiceAddress + switch service.ServiceAddress { + case "": + m[catalogServiceServiceAddress] = service.Address + default: + m[catalogServiceServiceAddress] = service.ServiceAddress + } m[catalogServiceServiceEnableTagOverride] = fmt.Sprintf("%t", service.ServiceEnableTagOverride) m[catalogServiceServiceID] = service.ServiceID m[catalogServiceServiceName] = service.ServiceName m[catalogServiceServicePort] = fmt.Sprintf("%d", service.ServicePort) + sort.Strings(service.ServiceTags) m[catalogServiceServiceTags] = service.ServiceTags m[catalogServiceTaggedAddresses] = service.TaggedAddresses - { - const initNumTaggedAddrs = 2 - taggedAddrs := make(map[string]interface{}, initNumTaggedAddrs) - if addr, found := service.TaggedAddresses[apiTaggedLAN]; found { - taggedAddrs[schemaTaggedLAN] = addr - } - if addr, found := service.TaggedAddresses[apiTaggedWAN]; found { - taggedAddrs[schemaTaggedWAN] = addr - } - m[catalogServiceTaggedAddresses] = taggedAddrs - } - l = append(l, m) } @@ -197,9 +192,10 @@ func dataSourceConsulCatalogServiceRead(d *schema.ResourceData, meta interface{} d.SetId(fmt.Sprintf(idKeyFmt, queryOpts.Datacenter, serviceName, serviceTag)) d.Set(catalogServiceDatacenter, queryOpts.Datacenter) + d.Set(catalogServiceName, serviceName) d.Set(catalogServiceTag, serviceTag) if err := d.Set(catalogServiceElem, l); err != nil { - return errwrap.Wrapf("Unable to store services: {{err}}", err) + return errwrap.Wrapf("Unable to store service: {{err}}", err) } return nil diff --git a/builtin/providers/consul/query_options.go b/builtin/providers/consul/query_options.go index 41348fba50e4..1cce0fabe6eb 100644 --- a/builtin/providers/consul/query_options.go +++ b/builtin/providers/consul/query_options.go @@ -49,12 +49,10 @@ var schemaQueryOpts = &schema.Schema{ }, queryOptToken: &schema.Schema{ Optional: true, - Default: true, Type: schema.TypeString, }, queryOptWaitIndex: &schema.Schema{ Optional: true, - Default: true, Type: schema.TypeInt, ValidateFunc: makeValidationFunc(queryOptWaitIndex, []interface{}{ validateIntMin(0), @@ -62,7 +60,6 @@ var schemaQueryOpts = &schema.Schema{ }, queryOptWaitTime: &schema.Schema{ Optional: true, - Default: true, Type: schema.TypeString, ValidateFunc: makeValidationFunc(queryOptWaitTime, []interface{}{ validateDurationMin("0ns"), diff --git a/website/source/docs/providers/consul/d/service.html.markdown b/website/source/docs/providers/consul/d/service.html.markdown new file mode 100644 index 000000000000..d0cf8a47630c --- /dev/null +++ b/website/source/docs/providers/consul/d/service.html.markdown @@ -0,0 +1,112 @@ +--- +layout: "consul" +page_title: "Consul: consul_catalog_service" +sidebar_current: "docs-consul-data-source-catalog-service" +description: |- + Provides details about a specific Consul service +--- + +# consul\_catalog\_service + +`consul_catalog_service` provides details about a specific Consul service in a +given datacenter. The results include a list of nodes advertising the specified +service, the node's IP address, port number, node ID, etc. By specifying a +different datacenter in the `query_options` it is possible to retrieve a list of +services from a different WAN-attached Consul datacenter. + +This data source is different from the `consul_catalog_services` (plural) data +source, which provides a summary of the current Consul services. + +## Example Usage + +``` +data "consul_catalog_service" "read-consul-dc1" { + # query_options { + # # Optional parameter: implicitly uses the current datacenter of the agent + # datacenter = "dc1" + # } + + name = "consul" +} + +# Set the description to a whitespace delimited list of the node names +resource "example_resource" "app" { + description = "${join(" ", data.consul_catalog_service.nodes)}" + ... +} +``` + +## Argument Reference + +The following arguments are supported: + +* `datacenter` - (Optional) The Consul datacenter to query. Defaults to the + same value found in `query_options` parameter specified below, or if that is + empty, the `datacenter` value found in the Consul agent that this provider is + configured to talk to. + +* `name` - (Required) The service name to select. + +* `query_options` - (Optional) See below. + +* `tag` - (Optional) A single tag that can be used to filter the list of nodes + to return based on a single matching tag.. + +The `query_options` block supports the following: + +* `allow_stale` - (Optional) When `true`, the default, allow responses from + Consul servers that are followers. + +* `require_consistent` - (Optional) When `true` force the client to perform a + read on at least quorum servers and verify the result is the same. Defaults + to `false`. + +* `token` - (Optional) Specify the Consul ACL token to use when performing the + request. This defaults to the same API token configured by the `consul` + provider but may be overriden if necessary. + +* `wait_index` - (Optional) Index number used to enable blocking quereis. + +* `wait_time` - (Optional) Max time the client should wait for a blocking query + to return. + +## Attributes Reference + +The following attributes are exported: + +* `datacenter` - The datacenter the keys are being read from to. +* `name` - The name of the service +* `tag` - The name of the tag used to filter the list of nodes in `service`. +* `service` - A list of nodes and details about each endpoint advertising a + service. Each element in the list is a map of attributes that correspond to + each individual node. The list of per-node attributes is detailed below. + +The following is a list of the per-node `service` attributes: + +* [`create_index`](https://www.consul.io/docs/agent/http/catalog.html#CreateIndex) - + The index entry at which point this entry was added to the catalog. +* [`modify_index`](https://www.consul.io/docs/agent/http/catalog.html#ModifyIndex) - + The index entry at which point this entry was modified in the catalog. +* [`node_address`](https://www.consul.io/docs/agent/http/catalog.html#Address) - + The address of the Consul node advertising the service. +* `node_id` - The Node ID of the Consul agent advertising the service. +* [`node_meta`](https://www.consul.io/docs/agent/http/catalog.html#Meta) - Node + meta data tag information, if any. +* [`node_name`](https://www.consul.io/docs/agent/http/catalog.html#Node) - The + name of the Consul node. +* [`address`](https://www.consul.io/docs/agent/http/catalog.html#ServiceAddress) - + The IP address of the service. If the `ServiceAddress` in the Consul catalog + is empty, this value is automatically populated with the `node_address` (the + `Address` in the Consul Catalog). +* [`enable_tag_override`](https://www.consul.io/docs/agent/http/catalog.html#ServiceEnableTagOverride) - + Whether service tags can be overridden on this service. +* [`id`](https://www.consul.io/docs/agent/http/catalog.html#ServiceID) - A + unique service instance identifier. +* [`name`](https://www.consul.io/docs/agent/http/catalog.html#ServiceName) - The + name of the service. +* [`port`](https://www.consul.io/docs/agent/http/catalog.html#ServicePort) - + Port number of the service. +* [`tagged_addresses`](https://www.consul.io/docs/agent/http/catalog.html#TaggedAddresses) - + List of explicit LAN and WAN IP addresses for the agent. +* [`tags`](https://www.consul.io/docs/agent/http/catalog.html#ServiceTags) - + List of tags for the service. diff --git a/website/source/layouts/consul.erb b/website/source/layouts/consul.erb index 32e0efa1d130..ce12fc25e868 100644 --- a/website/source/layouts/consul.erb +++ b/website/source/layouts/consul.erb @@ -13,6 +13,9 @@ > Data Sources