Skip to content

Commit e6c3fd2

Browse files
authored
Use tags and selectors to allow registering one port under couple of names (#140)
1 parent 8fa54b2 commit e6c3fd2

2 files changed

Lines changed: 113 additions & 19 deletions

File tree

hook/consul/hook.go

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -102,26 +102,29 @@ func (h *Hook) RegisterIntoConsul(taskInfo mesosutils.TaskInfo) error {
102102

103103
var instancesToRegister []instance
104104
for _, port := range ports {
105-
portServiceName, err := getServiceLabel(port)
105+
portServiceNames, err := getServiceLabels(port)
106106
if err != nil {
107107
log.Debugf("Pre-registration check for port failed: %s", err.Error())
108108
continue
109109
}
110-
// consulServiceID is generated the same way as it is in marathon-consul - because
111-
// it registers the service
112-
// See: https://github.com/allegro/marathon-consul/blob/v1.1.0/consul/consul.go#L299-L301
113-
consulServiceID := fmt.Sprintf("%s_%s_%d", taskID, portServiceName, port.GetNumber())
114-
marathonTaskTag := fmt.Sprintf("marathon-task:%s", taskID)
115-
portTags := mesosutils.GetLabelKeysByValue(port.GetLabels().GetLabels(), consulTagValue)
116-
portTags = append(portTags, globalTags...)
117-
portTags = append(portTags, marathonTaskTag)
118-
log.Infof("Adding service ID %q to deregister before termination", consulServiceID)
119-
instancesToRegister = append(instancesToRegister, instance{
120-
consulServiceName: portServiceName,
121-
consulServiceID: consulServiceID,
122-
port: port.GetNumber(),
123-
tags: portTags,
124-
})
110+
111+
for _, portServiceName := range portServiceNames {
112+
// consulServiceID is generated the same way as it is in marathon-consul - because
113+
// it registers the service
114+
// See: https://github.com/allegro/marathon-consul/blob/v1.1.0/consul/consul.go#L299-L301
115+
consulServiceID := fmt.Sprintf("%s_%s_%d", taskID, portServiceName, port.GetNumber())
116+
marathonTaskTag := fmt.Sprintf("marathon-task:%s", taskID)
117+
portTags := getPortTags(port, portServiceName)
118+
portTags = append(portTags, globalTags...)
119+
portTags = append(portTags, marathonTaskTag)
120+
log.Infof("Adding service ID %q to deregister before termination", consulServiceID)
121+
instancesToRegister = append(instancesToRegister, instance{
122+
consulServiceName: portServiceName,
123+
consulServiceID: consulServiceID,
124+
port: port.GetNumber(),
125+
tags: portTags,
126+
})
127+
}
125128
}
126129

127130
if len(instancesToRegister) == 0 {
@@ -161,6 +164,28 @@ func (h *Hook) RegisterIntoConsul(taskInfo mesosutils.TaskInfo) error {
161164
return nil
162165
}
163166

167+
func getPortTags(port mesos.Port, serviceName string) []string {
168+
var keys []string
169+
labels := port.GetLabels().GetLabels()
170+
171+
for _, label := range labels {
172+
value := label.GetValue()
173+
valueAndSelector := strings.Split(value, ":")
174+
if len(valueAndSelector) > 1 {
175+
value := valueAndSelector[0]
176+
serviceSelector := valueAndSelector[1]
177+
178+
if value == consulTagValue && serviceSelector == serviceName {
179+
keys = append(keys, label.GetKey())
180+
}
181+
} else if value == consulTagValue {
182+
keys = append(keys, label.GetKey())
183+
}
184+
}
185+
186+
return keys
187+
}
188+
164189
// DeregisterFromConsul will deregister service IDs from Consul that were created
165190
// during AfterTaskStartEvent hook event.
166191
func (h *Hook) DeregisterFromConsul(taskInfo mesosutils.TaskInfo) error {
@@ -220,12 +245,15 @@ func resolvePlaceholders(values []string, placeholders map[string]string) []stri
220245
return resolved
221246
}
222247

223-
func getServiceLabel(port mesos.Port) (string, error) {
248+
func getServiceLabels(port mesos.Port) ([]string, error) {
224249
label := mesosutils.FindLabel(port.GetLabels().GetLabels(), consulNameLabelKey)
225250
if label == nil {
226-
return "", fmt.Errorf("port %d has no label %q", port.GetNumber(), consulNameLabelKey)
251+
return nil, fmt.Errorf("port %d has no label %q", port.GetNumber(), consulNameLabelKey)
227252
}
228-
return label.GetValue(), nil
253+
254+
labels := strings.Split(label.GetValue(), ",")
255+
256+
return labels, nil
229257
}
230258

231259
func marathonAppNameToServiceName(name mesosutils.TaskID) string {

hook/consul/hook_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,72 @@ func TestIfUsesLabelledPortsForServiceIDGenAndRegisterMultiplePorts(t *testing.T
155155
require.Contains(t, services, consulNameSecond)
156156
}
157157

158+
func TestIfUsesCompoundLabelledPortsForServiceIDGenAndRegisterSinglePortWithMultipleNames(t *testing.T) {
159+
// given
160+
consulName := "consulName,consulName-secured"
161+
taskID := "taskID"
162+
securedTagValue := "tag:consulName-secured"
163+
insecureTagValue := "tag:consulName"
164+
commonTagValue := "tag"
165+
taskInfo := prepareTaskInfo(taskID, consulName, consulName, []string{"metrics"}, []mesos.Port{
166+
{
167+
Number: 998,
168+
Labels: &mesos.Labels{
169+
Labels: []mesos.Label{
170+
{
171+
Key: "consul",
172+
Value: &consulName,
173+
},
174+
{
175+
Key: "secure",
176+
Value: &securedTagValue,
177+
},
178+
{
179+
Key: "insecure",
180+
Value: &insecureTagValue,
181+
},
182+
{
183+
Key: "common",
184+
Value: &commonTagValue,
185+
},
186+
},
187+
},
188+
},
189+
})
190+
expectedService := instance{
191+
consulServiceName: "consulName",
192+
consulServiceID: createServiceID(taskID, "consulName", 998),
193+
port: 998,
194+
tags: []string{"insecure", "common", "metrics", "marathon", "marathon-task:taskID"},
195+
}
196+
expectedService2 := instance{
197+
consulServiceName: "consulName-secured",
198+
consulServiceID: createServiceID(taskID, "consulName-secured", 998),
199+
port: 998,
200+
tags: []string{"secure", "common", "metrics", "marathon", "marathon-task:taskID"},
201+
}
202+
203+
// Create a test Consul server
204+
config, server := createTestConsulServer(t)
205+
client, _ := api.NewClient(config) // #nosec
206+
defer stopConsul(server)
207+
208+
h := &Hook{config: Config{ConsulGlobalTag: "marathon"}, client: client}
209+
210+
// when
211+
err := h.RegisterIntoConsul(taskInfo)
212+
opts := api.QueryOptions{}
213+
services, _, err := client.Catalog().Services(&opts)
214+
215+
// then
216+
require.NoError(t, err)
217+
require.Len(t, h.serviceInstances, 2)
218+
require.Contains(t, services, "consulName")
219+
requireEqualElements(t, expectedService.tags, services["consulName"])
220+
require.Contains(t, services, "consulName-secured")
221+
requireEqualElements(t, expectedService2.tags, services["consulName-secured"])
222+
}
223+
158224
func TestIfUsesPortLabelsForRegistration(t *testing.T) {
159225
consulName := "consulName"
160226
consulNameSecond := "consulName-secured"

0 commit comments

Comments
 (0)