github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/command/agent/consul/catalog_testing.go (about) 1 package consul 2 3 import ( 4 "fmt" 5 "sync" 6 7 "github.com/hashicorp/consul/api" 8 "github.com/hashicorp/go-hclog" 9 "github.com/hashicorp/nomad/helper" 10 ) 11 12 // MockCatalog can be used for testing where the CatalogAPI is needed. 13 type MockCatalog struct { 14 logger hclog.Logger 15 } 16 17 func NewMockCatalog(l hclog.Logger) *MockCatalog { 18 return &MockCatalog{logger: l.Named("mock_consul")} 19 } 20 21 func (m *MockCatalog) Datacenters() ([]string, error) { 22 dcs := []string{"dc1"} 23 m.logger.Trace("Datacenters()", "dcs", dcs, "error", "nil") 24 return dcs, nil 25 } 26 27 func (m *MockCatalog) Service(service, tag string, q *api.QueryOptions) ([]*api.CatalogService, *api.QueryMeta, error) { 28 m.logger.Trace("Services()", "service", service, "tag", tag, "query_options", q) 29 return nil, nil, nil 30 } 31 32 // MockAgent is a fake in-memory Consul backend for ServiceClient. 33 type MockAgent struct { 34 // maps of what services and checks have been registered 35 services map[string]*api.AgentServiceRegistration 36 checks map[string]*api.AgentCheckRegistration 37 38 // hits is the total number of times agent methods have been called 39 hits int 40 41 // mu guards above fields 42 mu sync.Mutex 43 44 // when UpdateTTL is called the check ID will have its counter inc'd 45 checkTTLs map[string]int 46 47 // What check status to return from Checks() 48 checkStatus string 49 } 50 51 // NewMockAgent that returns all checks as passing. 52 func NewMockAgent() *MockAgent { 53 return &MockAgent{ 54 services: make(map[string]*api.AgentServiceRegistration), 55 checks: make(map[string]*api.AgentCheckRegistration), 56 checkTTLs: make(map[string]int), 57 checkStatus: api.HealthPassing, 58 } 59 } 60 61 // getHits returns how many Consul Agent API calls have been made. 62 func (c *MockAgent) getHits() int { 63 c.mu.Lock() 64 defer c.mu.Unlock() 65 return c.hits 66 } 67 68 // SetStatus that Checks() should return. Returns old status value. 69 func (c *MockAgent) SetStatus(s string) string { 70 c.mu.Lock() 71 old := c.checkStatus 72 c.checkStatus = s 73 c.mu.Unlock() 74 return old 75 } 76 77 func (c *MockAgent) Self() (map[string]map[string]interface{}, error) { 78 c.mu.Lock() 79 defer c.mu.Unlock() 80 c.hits++ 81 82 s := map[string]map[string]interface{}{ 83 "Member": { 84 "Addr": "127.0.0.1", 85 "DelegateCur": 4, 86 "DelegateMax": 5, 87 "DelegateMin": 2, 88 "Name": "rusty", 89 "Port": 8301, 90 "ProtocolCur": 2, 91 "ProtocolMax": 5, 92 "ProtocolMin": 1, 93 "Status": 1, 94 "Tags": map[string]interface{}{ 95 "build": "0.8.1:'e9ca44d", 96 }, 97 }, 98 "xDS": { 99 "SupportedProxies": map[string]interface{}{ 100 "envoy": []interface{}{ 101 "1.14.2", 102 "1.13.2", 103 "1.12.4", 104 "1.11.2", 105 }, 106 }, 107 }, 108 } 109 return s, nil 110 } 111 112 func (c *MockAgent) Services() (map[string]*api.AgentService, error) { 113 c.mu.Lock() 114 defer c.mu.Unlock() 115 c.hits++ 116 117 r := make(map[string]*api.AgentService, len(c.services)) 118 for k, v := range c.services { 119 r[k] = &api.AgentService{ 120 ID: v.ID, 121 Service: v.Name, 122 Tags: make([]string, len(v.Tags)), 123 Meta: helper.CopyMapStringString(v.Meta), 124 Port: v.Port, 125 Address: v.Address, 126 EnableTagOverride: v.EnableTagOverride, 127 } 128 copy(r[k].Tags, v.Tags) 129 } 130 return r, nil 131 } 132 133 // Checks implements the Agent API Checks method. 134 func (c *MockAgent) Checks() (map[string]*api.AgentCheck, error) { 135 c.mu.Lock() 136 defer c.mu.Unlock() 137 c.hits++ 138 139 r := make(map[string]*api.AgentCheck, len(c.checks)) 140 for k, v := range c.checks { 141 r[k] = &api.AgentCheck{ 142 CheckID: v.ID, 143 Name: v.Name, 144 Status: c.checkStatus, 145 Notes: v.Notes, 146 ServiceID: v.ServiceID, 147 ServiceName: c.services[v.ServiceID].Name, 148 } 149 } 150 return r, nil 151 } 152 153 // CheckRegs returns the raw AgentCheckRegistrations registered with this mock 154 // agent. 155 func (c *MockAgent) CheckRegs() []*api.AgentCheckRegistration { 156 c.mu.Lock() 157 defer c.mu.Unlock() 158 regs := make([]*api.AgentCheckRegistration, 0, len(c.checks)) 159 for _, check := range c.checks { 160 regs = append(regs, check) 161 } 162 return regs 163 } 164 165 func (c *MockAgent) CheckRegister(check *api.AgentCheckRegistration) error { 166 c.mu.Lock() 167 defer c.mu.Unlock() 168 c.hits++ 169 170 c.checks[check.ID] = check 171 172 // Be nice and make checks reachable-by-service 173 scheck := check.AgentServiceCheck 174 c.services[check.ServiceID].Checks = append(c.services[check.ServiceID].Checks, &scheck) 175 return nil 176 } 177 178 func (c *MockAgent) CheckDeregister(checkID string) error { 179 c.mu.Lock() 180 defer c.mu.Unlock() 181 c.hits++ 182 delete(c.checks, checkID) 183 delete(c.checkTTLs, checkID) 184 return nil 185 } 186 187 func (c *MockAgent) ServiceRegister(service *api.AgentServiceRegistration) error { 188 c.mu.Lock() 189 defer c.mu.Unlock() 190 c.hits++ 191 c.services[service.ID] = service 192 return nil 193 } 194 195 func (c *MockAgent) ServiceDeregister(serviceID string) error { 196 c.mu.Lock() 197 defer c.mu.Unlock() 198 c.hits++ 199 delete(c.services, serviceID) 200 for k, v := range c.checks { 201 if v.ServiceID == serviceID { 202 delete(c.checks, k) 203 delete(c.checkTTLs, k) 204 } 205 } 206 return nil 207 } 208 209 func (c *MockAgent) UpdateTTL(id string, output string, status string) error { 210 c.mu.Lock() 211 defer c.mu.Unlock() 212 c.hits++ 213 214 check, ok := c.checks[id] 215 if !ok { 216 return fmt.Errorf("unknown check id: %q", id) 217 } 218 // Flip initial status to passing 219 check.Status = "passing" 220 c.checkTTLs[id]++ 221 return nil 222 } 223 224 // a convenience method for looking up a registered service by name 225 func (c *MockAgent) lookupService(name string) []*api.AgentServiceRegistration { 226 c.mu.Lock() 227 defer c.mu.Unlock() 228 229 var services []*api.AgentServiceRegistration 230 for _, service := range c.services { 231 if service.Name == name { 232 services = append(services, service) 233 } 234 } 235 return services 236 }