github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/client/serviceregistration/service_registration.go (about) 1 package serviceregistration 2 3 import ( 4 "context" 5 6 "github.com/hashicorp/consul/api" 7 "github.com/hashicorp/nomad/nomad/structs" 8 "golang.org/x/exp/maps" 9 ) 10 11 // Handler is the interface the Nomad Client uses to register, update and 12 // remove services and checks from service registration providers. Currently, 13 // Consul and Nomad are supported providers. 14 // 15 // When utilising Consul, the ACL "service:write" is required. It supports all 16 // functionality and is the OG/GOAT. 17 // 18 // When utilising Nomad, the client secret ID is used for authorisation. It 19 // currently supports service registrations only. 20 type Handler interface { 21 22 // RegisterWorkload adds all service entries and checks to the backend 23 // provider. Whilst callers attempt to ensure WorkloadServices.Services is 24 // not empty before calling this function, implementations should also 25 // perform this. 26 RegisterWorkload(workload *WorkloadServices) error 27 28 // RemoveWorkload all service entries and checks from the backend provider 29 // that are found within the passed WorkloadServices object. Whilst callers 30 // attempt to ensure WorkloadServices.Services is not empty before calling 31 // this function, implementations should also perform this. 32 RemoveWorkload(workload *WorkloadServices) 33 34 // UpdateWorkload removes workload as specified by the old parameter, and 35 // adds workload as specified by the new parameter. Callers do not perform 36 // any deduplication on both objects, it is therefore the responsibility of 37 // the implementation. 38 UpdateWorkload(old, newTask *WorkloadServices) error 39 40 // AllocRegistrations returns the registrations for the given allocation. 41 AllocRegistrations(allocID string) (*AllocRegistration, error) 42 43 // UpdateTTL is used to update the TTL of an individual service 44 // registration check. 45 UpdateTTL(id, namespace, output, status string) error 46 } 47 48 // WorkloadRestarter allows the checkWatcher to restart tasks or entire task 49 // groups. 50 type WorkloadRestarter interface { 51 Restart(ctx context.Context, event *structs.TaskEvent, failure bool) error 52 } 53 54 // AllocRegistration holds the status of services registered for a particular 55 // allocations by task. 56 type AllocRegistration struct { 57 // Tasks maps the name of a task to its registered services and checks. 58 Tasks map[string]*ServiceRegistrations 59 } 60 61 // Copy performs a deep copy of the AllocRegistration object. 62 func (a *AllocRegistration) Copy() *AllocRegistration { 63 c := &AllocRegistration{ 64 Tasks: make(map[string]*ServiceRegistrations, len(a.Tasks)), 65 } 66 67 for k, v := range a.Tasks { 68 c.Tasks[k] = v.copy() 69 } 70 71 return c 72 } 73 74 // NumServices returns the number of registered services. 75 func (a *AllocRegistration) NumServices() int { 76 if a == nil { 77 return 0 78 } 79 80 total := 0 81 for _, treg := range a.Tasks { 82 for _, sreg := range treg.Services { 83 if sreg.Service != nil { 84 total++ 85 } 86 } 87 } 88 89 return total 90 } 91 92 // NumChecks returns the number of registered checks. 93 func (a *AllocRegistration) NumChecks() int { 94 if a == nil { 95 return 0 96 } 97 98 total := 0 99 for _, treg := range a.Tasks { 100 for _, sreg := range treg.Services { 101 total += len(sreg.Checks) 102 } 103 } 104 105 return total 106 } 107 108 // ServiceRegistrations holds the status of services registered for a 109 // particular task or task group. 110 type ServiceRegistrations struct { 111 // Services maps service_id -> service registration 112 Services map[string]*ServiceRegistration 113 } 114 115 func (t *ServiceRegistrations) copy() *ServiceRegistrations { 116 c := &ServiceRegistrations{ 117 Services: make(map[string]*ServiceRegistration, len(t.Services)), 118 } 119 120 for k, v := range t.Services { 121 c.Services[k] = v.copy() 122 } 123 124 return c 125 } 126 127 // ServiceRegistration holds the status of a registered Consul Service and its 128 // Checks. 129 type ServiceRegistration struct { 130 // serviceID and checkIDs are internal fields that track just the IDs of the 131 // services/checks registered in Consul. It is used to materialize the other 132 // fields when queried. 133 ServiceID string 134 CheckIDs map[string]struct{} // todo: use a Set? 135 136 // CheckOnUpdate is a map of checkIDs and the associated OnUpdate value 137 // from the ServiceCheck It is used to determine how a reported checks 138 // status should be evaluated. 139 CheckOnUpdate map[string]string 140 141 // Service is the AgentService registered in Consul. 142 Service *api.AgentService 143 144 // Checks is the status of the registered checks. 145 Checks []*api.AgentCheck 146 } 147 148 func (s *ServiceRegistration) copy() *ServiceRegistration { 149 // Copy does not copy the external fields but only the internal fields. 150 // This is so that the caller of AllocRegistrations can not access the 151 // internal fields and that method uses these fields to populate the 152 // external fields. 153 return &ServiceRegistration{ 154 ServiceID: s.ServiceID, 155 CheckIDs: maps.Clone(s.CheckIDs), 156 CheckOnUpdate: maps.Clone(s.CheckOnUpdate), 157 } 158 }