Skip to content

Commit 4829ddc

Browse files
Propagate SvcExportCreationTimestamp to Endpoints (#200)
* Added managed by label - issue 110 * Propagate CreationTimestamp to Endpoints * intg - remove creationtimestamp in endpoint cmp * Change to UnixMillis & Rename to SvcExportCreationTimestamp * fix var being stored in CM * set svcExportCreationTimestamp to 0 when errors or not set
1 parent 2b6caea commit 4829ddc

File tree

7 files changed

+209
-161
lines changed

7 files changed

+209
-161
lines changed

integration/shared/scenarios/export_service.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ func (e *exportServiceScenario) compareEndpoints(cmEndpoints []*model.Endpoint)
112112
for _, actual := range cmEndpoints {
113113
// Ignore K8S instance attribute for the purpose of this test.
114114
delete(actual.Attributes, multiclustercontrollers.K8sVersionAttr)
115+
// Ignore SvcExportCreationTimestamp attribute for the purpose of this test by setting value to 0.
116+
actual.SvcExportCreationTimestamp = 0
115117
if expected.Equals(actual) {
116118
match = true
117119
break

pkg/cloudmap/client_test.go

Lines changed: 49 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cloudmap
22

33
import (
44
"context"
5+
"strconv"
56
"testing"
67

78
cloudmapMock "github.com/aws/aws-cloud-map-mcs-controller-for-k8s/mocks/pkg/cloudmap"
@@ -283,30 +284,32 @@ func TestServiceDiscoveryClient_RegisterEndpoints(t *testing.T) {
283284
tc.mockCache.EXPECT().GetServiceIdMap(test.HttpNsName).Return(getServiceIdMapForTest(), true)
284285

285286
attrs1 := map[string]string{
286-
model.ClusterIdAttr: test.ClusterId1,
287-
model.ClusterSetIdAttr: test.ClusterSetId1,
288-
model.EndpointIpv4Attr: test.EndptIp1,
289-
model.EndpointPortAttr: test.PortStr1,
290-
model.EndpointPortNameAttr: test.PortName1,
291-
model.EndpointProtocolAttr: test.Protocol1,
292-
model.ServicePortNameAttr: test.PortName1,
293-
model.ServicePortAttr: test.ServicePortStr1,
294-
model.ServiceProtocolAttr: test.Protocol1,
295-
model.ServiceTargetPortAttr: test.PortStr1,
296-
model.ServiceTypeAttr: test.SvcType,
287+
model.ClusterIdAttr: test.ClusterId1,
288+
model.ClusterSetIdAttr: test.ClusterSetId1,
289+
model.EndpointIpv4Attr: test.EndptIp1,
290+
model.EndpointPortAttr: test.PortStr1,
291+
model.EndpointPortNameAttr: test.PortName1,
292+
model.EndpointProtocolAttr: test.Protocol1,
293+
model.ServicePortNameAttr: test.PortName1,
294+
model.ServicePortAttr: test.ServicePortStr1,
295+
model.ServiceProtocolAttr: test.Protocol1,
296+
model.ServiceTargetPortAttr: test.PortStr1,
297+
model.ServiceTypeAttr: test.SvcType,
298+
model.SvcExportCreationTimestampAttr: strconv.FormatInt(test.SvcExportCreationTimestamp, 10),
297299
}
298300
attrs2 := map[string]string{
299-
model.ClusterIdAttr: test.ClusterId1,
300-
model.ClusterSetIdAttr: test.ClusterSetId1,
301-
model.EndpointIpv4Attr: test.EndptIp2,
302-
model.EndpointPortAttr: test.PortStr2,
303-
model.EndpointPortNameAttr: test.PortName2,
304-
model.EndpointProtocolAttr: test.Protocol2,
305-
model.ServicePortNameAttr: test.PortName2,
306-
model.ServicePortAttr: test.ServicePortStr2,
307-
model.ServiceProtocolAttr: test.Protocol2,
308-
model.ServiceTargetPortAttr: test.PortStr2,
309-
model.ServiceTypeAttr: test.SvcType,
301+
model.ClusterIdAttr: test.ClusterId1,
302+
model.ClusterSetIdAttr: test.ClusterSetId1,
303+
model.EndpointIpv4Attr: test.EndptIp2,
304+
model.EndpointPortAttr: test.PortStr2,
305+
model.EndpointPortNameAttr: test.PortName2,
306+
model.EndpointProtocolAttr: test.Protocol2,
307+
model.ServicePortNameAttr: test.PortName2,
308+
model.ServicePortAttr: test.ServicePortStr2,
309+
model.ServiceProtocolAttr: test.Protocol2,
310+
model.ServiceTargetPortAttr: test.PortStr2,
311+
model.ServiceTypeAttr: test.SvcType,
312+
model.SvcExportCreationTimestampAttr: strconv.FormatInt(test.SvcExportCreationTimestamp, 10),
310313
}
311314

312315
tc.mockApi.EXPECT().RegisterInstance(context.TODO(), test.SvcId, test.EndptId1, attrs1).
@@ -371,33 +374,35 @@ func getHttpInstanceSummaryForTest() []types.HttpInstanceSummary {
371374
{
372375
InstanceId: aws.String(test.EndptId1),
373376
Attributes: map[string]string{
374-
model.ClusterIdAttr: test.ClusterId1,
375-
model.ClusterSetIdAttr: test.ClusterSetId1,
376-
model.EndpointIpv4Attr: test.EndptIp1,
377-
model.EndpointPortAttr: test.PortStr1,
378-
model.EndpointPortNameAttr: test.PortName1,
379-
model.EndpointProtocolAttr: test.Protocol1,
380-
model.ServicePortNameAttr: test.PortName1,
381-
model.ServicePortAttr: test.ServicePortStr1,
382-
model.ServiceProtocolAttr: test.Protocol1,
383-
model.ServiceTargetPortAttr: test.PortStr1,
384-
model.ServiceTypeAttr: test.SvcType,
377+
model.ClusterIdAttr: test.ClusterId1,
378+
model.ClusterSetIdAttr: test.ClusterSetId1,
379+
model.EndpointIpv4Attr: test.EndptIp1,
380+
model.EndpointPortAttr: test.PortStr1,
381+
model.EndpointPortNameAttr: test.PortName1,
382+
model.EndpointProtocolAttr: test.Protocol1,
383+
model.ServicePortNameAttr: test.PortName1,
384+
model.ServicePortAttr: test.ServicePortStr1,
385+
model.ServiceProtocolAttr: test.Protocol1,
386+
model.ServiceTargetPortAttr: test.PortStr1,
387+
model.ServiceTypeAttr: test.SvcType,
388+
model.SvcExportCreationTimestampAttr: strconv.FormatInt(test.SvcExportCreationTimestamp, 10),
385389
},
386390
},
387391
{
388392
InstanceId: aws.String(test.EndptId2),
389393
Attributes: map[string]string{
390-
model.ClusterIdAttr: test.ClusterId1,
391-
model.ClusterSetIdAttr: test.ClusterSetId1,
392-
model.EndpointIpv4Attr: test.EndptIp2,
393-
model.EndpointPortAttr: test.PortStr2,
394-
model.EndpointPortNameAttr: test.PortName2,
395-
model.EndpointProtocolAttr: test.Protocol2,
396-
model.ServicePortNameAttr: test.PortName2,
397-
model.ServicePortAttr: test.ServicePortStr2,
398-
model.ServiceProtocolAttr: test.Protocol2,
399-
model.ServiceTargetPortAttr: test.PortStr2,
400-
model.ServiceTypeAttr: test.SvcType,
394+
model.ClusterIdAttr: test.ClusterId1,
395+
model.ClusterSetIdAttr: test.ClusterSetId1,
396+
model.EndpointIpv4Attr: test.EndptIp2,
397+
model.EndpointPortAttr: test.PortStr2,
398+
model.EndpointPortNameAttr: test.PortName2,
399+
model.EndpointProtocolAttr: test.Protocol2,
400+
model.ServicePortNameAttr: test.PortName2,
401+
model.ServicePortAttr: test.ServicePortStr2,
402+
model.ServiceProtocolAttr: test.Protocol2,
403+
model.ServiceTargetPortAttr: test.PortStr2,
404+
model.ServiceTypeAttr: test.SvcType,
405+
model.SvcExportCreationTimestampAttr: strconv.FormatInt(test.SvcExportCreationTimestamp, 10),
401406
},
402407
},
403408
}

pkg/controllers/multicluster/controllers_common_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package controllers
22

33
import (
4+
"time"
5+
46
multiclusterv1alpha1 "github.com/aws/aws-cloud-map-mcs-controller-for-k8s/pkg/apis/multicluster/v1alpha1"
57
"github.com/aws/aws-cloud-map-mcs-controller-for-k8s/test"
68
"github.com/aws/aws-sdk-go-v2/aws"
@@ -41,10 +43,12 @@ func k8sServiceForTest() *v1.Service {
4143
}
4244

4345
func serviceExportForTest() *multiclusterv1alpha1.ServiceExport {
46+
creationTimestamp := metav1.NewTime(time.UnixMilli(test.SvcExportCreationTimestamp))
4447
return &multiclusterv1alpha1.ServiceExport{
4548
ObjectMeta: metav1.ObjectMeta{
46-
Name: test.SvcName,
47-
Namespace: test.HttpNsName,
49+
Name: test.SvcName,
50+
Namespace: test.HttpNsName,
51+
CreationTimestamp: creationTimestamp,
4852
},
4953
}
5054
}

pkg/controllers/multicluster/serviceexport_controller.go

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ func (r *ServiceExportReconciler) handleUpdate(ctx context.Context, serviceExpor
139139
return ctrl.Result{}, err
140140
}
141141

142-
endpoints, err := r.extractEndpoints(ctx, service)
142+
endpoints, err := r.extractEndpoints(ctx, service, serviceExport)
143143
if err != nil {
144144
r.Log.Error(err, "error extracting Endpoints",
145145
"namespace", serviceExport.Namespace, "name", serviceExport.Name)
@@ -230,7 +230,7 @@ func (r *ServiceExportReconciler) handleDelete(ctx context.Context, serviceExpor
230230
return ctrl.Result{}, nil
231231
}
232232

233-
func (r *ServiceExportReconciler) extractEndpoints(ctx context.Context, svc *v1.Service) ([]*model.Endpoint, error) {
233+
func (r *ServiceExportReconciler) extractEndpoints(ctx context.Context, svc *v1.Service, svcExport *multiclusterv1alpha1.ServiceExport) ([]*model.Endpoint, error) {
234234
result := make([]*model.Endpoint, 0)
235235

236236
endpointSlices := discovery.EndpointSliceList{}
@@ -259,6 +259,11 @@ func (r *ServiceExportReconciler) extractEndpoints(ctx context.Context, svc *v1.
259259
return nil, err
260260
}
261261

262+
var svcExportCreationTimestamp int64 = 0
263+
if !svcExport.ObjectMeta.CreationTimestamp.IsZero() {
264+
svcExportCreationTimestamp = svcExport.ObjectMeta.CreationTimestamp.Time.UnixMilli()
265+
}
266+
262267
for _, slice := range endpointSlices.Items {
263268
if slice.AddressType != discovery.AddressTypeIPv4 {
264269
return nil, fmt.Errorf("unsupported address type %s for service %s", slice.AddressType, svc.Name)
@@ -275,14 +280,15 @@ func (r *ServiceExportReconciler) extractEndpoints(ctx context.Context, svc *v1.
275280

276281
port := EndpointPortToPort(endpointPort)
277282
result = append(result, &model.Endpoint{
278-
Id: model.EndpointIdFromIPAddressAndPort(IP, port),
279-
IP: IP,
280-
EndpointPort: port,
281-
ServicePort: servicePortMap[*endpointPort.Name],
282-
ClusterId: clusterId,
283-
ClusterSetId: clusterSetId,
284-
ServiceType: serviceType,
285-
Attributes: attributes,
283+
Id: model.EndpointIdFromIPAddressAndPort(IP, port),
284+
IP: IP,
285+
EndpointPort: port,
286+
ServicePort: servicePortMap[*endpointPort.Name],
287+
ClusterId: clusterId,
288+
ClusterSetId: clusterSetId,
289+
ServiceType: serviceType,
290+
SvcExportCreationTimestamp: svcExportCreationTimestamp,
291+
Attributes: attributes,
286292
})
287293
}
288294
}

pkg/model/types.go

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,15 @@ type ServiceType string
4242

4343
// Endpoint holds basic values and attributes for an endpoint.
4444
type Endpoint struct {
45-
Id string
46-
IP string
47-
EndpointPort Port
48-
ServicePort Port
49-
ClusterId string
50-
ClusterSetId string
51-
ServiceType ServiceType
52-
Attributes map[string]string
45+
Id string
46+
IP string
47+
EndpointPort Port
48+
ServicePort Port
49+
ClusterId string
50+
ClusterSetId string
51+
ServiceType ServiceType
52+
SvcExportCreationTimestamp int64
53+
Attributes map[string]string
5354
}
5455

5556
type Port struct {
@@ -62,17 +63,18 @@ type Port struct {
6263
// Cloudmap Instances IP and Port is supposed to be AWS_INSTANCE_IPV4 and AWS_INSTANCE_PORT
6364
// Rest are custom attributes
6465
const (
65-
EndpointIpv4Attr = "AWS_INSTANCE_IPV4"
66-
EndpointPortAttr = "AWS_INSTANCE_PORT"
67-
EndpointPortNameAttr = "ENDPOINT_PORT_NAME"
68-
EndpointProtocolAttr = "ENDPOINT_PROTOCOL"
69-
ClusterIdAttr = "CLUSTER_ID"
70-
ClusterSetIdAttr = "CLUSTERSET_ID"
71-
ServicePortNameAttr = "SERVICE_PORT_NAME"
72-
ServicePortAttr = "SERVICE_PORT"
73-
ServiceTargetPortAttr = "SERVICE_TARGET_PORT"
74-
ServiceProtocolAttr = "SERVICE_PROTOCOL"
75-
ServiceTypeAttr = "SERVICE_TYPE"
66+
SvcExportCreationTimestampAttr = "SVC_EXPORT_CREATION_TIMESTAMP"
67+
EndpointIpv4Attr = "AWS_INSTANCE_IPV4"
68+
EndpointPortAttr = "AWS_INSTANCE_PORT"
69+
EndpointPortNameAttr = "ENDPOINT_PORT_NAME"
70+
EndpointProtocolAttr = "ENDPOINT_PROTOCOL"
71+
ClusterIdAttr = "CLUSTER_ID"
72+
ClusterSetIdAttr = "CLUSTERSET_ID"
73+
ServicePortNameAttr = "SERVICE_PORT_NAME"
74+
ServicePortAttr = "SERVICE_PORT"
75+
ServiceTargetPortAttr = "SERVICE_TARGET_PORT"
76+
ServiceProtocolAttr = "SERVICE_PROTOCOL"
77+
ServiceTypeAttr = "SERVICE_TYPE"
7678
)
7779

7880
// NewEndpointFromInstance converts a Cloud Map HttpInstanceSummary to an endpoint.
@@ -119,6 +121,10 @@ func NewEndpointFromInstance(inst *types.HttpInstanceSummary) (*Endpoint, error)
119121
return nil, err
120122
}
121123

124+
if endpoint.SvcExportCreationTimestamp, err = removeTimestampAttr(attributes, SvcExportCreationTimestampAttr); err != nil {
125+
endpoint.SvcExportCreationTimestamp = 0
126+
}
127+
122128
// Add the remaining attributes
123129
endpoint.Attributes = attributes
124130

@@ -177,6 +183,19 @@ func removeIntAttr(attributes map[string]string, attr string) (int32, error) {
177183
return 0, fmt.Errorf("cannot find the attribute %s", attr)
178184
}
179185

186+
func removeTimestampAttr(attributes map[string]string, attr string) (int64, error) {
187+
if value, hasValue := attributes[attr]; hasValue {
188+
parsedValue, parseError := strconv.ParseInt(value, 10, 64)
189+
if parseError != nil {
190+
return 0, fmt.Errorf("failed to parse the %s as int with error %s",
191+
attr, parseError.Error())
192+
}
193+
delete(attributes, attr)
194+
return parsedValue, nil
195+
}
196+
return 0, fmt.Errorf("cannot find the attribute %s", attr)
197+
}
198+
180199
// GetCloudMapAttributes extracts endpoint attributes for Cloud Map service instance registration.
181200
func (e *Endpoint) GetCloudMapAttributes() map[string]string {
182201
attrs := make(map[string]string)
@@ -192,6 +211,7 @@ func (e *Endpoint) GetCloudMapAttributes() map[string]string {
192211
attrs[ServiceTargetPortAttr] = e.ServicePort.TargetPort
193212
attrs[ServiceProtocolAttr] = e.ServicePort.Protocol
194213
attrs[ServiceTypeAttr] = e.ServiceType.String()
214+
attrs[SvcExportCreationTimestampAttr] = strconv.FormatInt(e.SvcExportCreationTimestamp, 10)
195215

196216
for key, val := range e.Attributes {
197217
attrs[key] = val

0 commit comments

Comments
 (0)