@ -105,28 +105,40 @@ func TestTailscaleEgressServices(t *testing.T) {
condition ( tsapi . ProxyGroupReady , metav1 . ConditionTrue , "" , "" , clock ) ,
}
} )
// Quirks of the fake client.
mustUpdateStatus ( t , fc , "default" , "test" , func ( svc * corev1 . Service ) {
svc . Status . Conditions = [ ] metav1 . Condition { }
expectReconciled ( t , esr , "default" , "test" )
validateReadyService ( t , fc , esr , svc , clock , zl , cm )
} )
t . Run ( "service_retain_one_unnamed_port" , func ( t * testing . T ) {
svc . Spec . Ports = [ ] corev1 . ServicePort { { Protocol : "TCP" , Port : 80 } }
mustUpdate ( t , fc , "default" , "test" , func ( s * corev1 . Service ) {
s . Spec . Ports = svc . Spec . Ports
} )
expectReconciled ( t , esr , "default" , "test" )
// Verify that a ClusterIP Service has been created.
name := findGenNameForEgressSvcResources ( t , fc , svc )
expectEqual ( t , fc , clusterIPSvc ( name , svc ) , removeTargetPortsFromSvc )
clusterSvc := mustGetClusterIPSvc ( t , fc , name )
// Verify that an EndpointSlice has been created.
expectEqual ( t , fc , endpointSlice ( name , svc , clusterSvc ) , nil )
// Verify that ConfigMap contains configuration for the new egress service.
mustHaveConfigForSvc ( t , fc , svc , clusterSvc , cm )
r := svcConfiguredReason ( svc , true , zl . Sugar ( ) )
// Verify that the user-created ExternalName Service has Configured set to true and ExternalName pointing to the
// CluterIP Service.
svc . Status . Conditions = [ ] metav1 . Condition {
condition ( tsapi . EgressSvcConfigured , metav1 . ConditionTrue , r , r , clock ) ,
}
svc . ObjectMeta . Finalizers = [ ] string { "tailscale.com/finalizer" }
svc . Spec . ExternalName = fmt . Sprintf ( "%s.operator-ns.svc.cluster.local" , name )
expectEqual ( t , fc , svc , nil )
validateReadyService ( t , fc , esr , svc , clock , zl , cm )
} )
t . Run ( "service_add_two_named_ports" , func ( t * testing . T ) {
svc . Spec . Ports = [ ] corev1 . ServicePort { { Protocol : "TCP" , Port : 80 , Name : "http" } , { Protocol : "TCP" , Port : 443 , Name : "https" } }
mustUpdate ( t , fc , "default" , "test" , func ( s * corev1 . Service ) {
s . Spec . Ports = svc . Spec . Ports
} )
expectReconciled ( t , esr , "default" , "test" )
validateReadyService ( t , fc , esr , svc , clock , zl , cm )
} )
t . Run ( "service_add_udp_port" , func ( t * testing . T ) {
svc . Spec . Ports = append ( svc . Spec . Ports , corev1 . ServicePort { Port : 53 , Protocol : "UDP" , Name : "dns" } )
mustUpdate ( t , fc , "default" , "test" , func ( s * corev1 . Service ) {
s . Spec . Ports = svc . Spec . Ports
} )
expectReconciled ( t , esr , "default" , "test" )
validateReadyService ( t , fc , esr , svc , clock , zl , cm )
} )
t . Run ( "service_change_protocol" , func ( t * testing . T ) {
svc . Spec . Ports = [ ] corev1 . ServicePort { { Protocol : "TCP" , Port : 80 , Name : "http" } , { Protocol : "TCP" , Port : 443 , Name : "https" } , { Port : 53 , Protocol : "TCP" , Name : "tcp_dns" } }
mustUpdate ( t , fc , "default" , "test" , func ( s * corev1 . Service ) {
s . Spec . Ports = svc . Spec . Ports
} )
expectReconciled ( t , esr , "default" , "test" )
validateReadyService ( t , fc , esr , svc , clock , zl , cm )
} )
t . Run ( "delete_external_name_service" , func ( t * testing . T ) {
@ -143,6 +155,29 @@ func TestTailscaleEgressServices(t *testing.T) {
} )
}
func validateReadyService ( t * testing . T , fc client . WithWatch , esr * egressSvcsReconciler , svc * corev1 . Service , clock * tstest . Clock , zl * zap . Logger , cm * corev1 . ConfigMap ) {
expectReconciled ( t , esr , "default" , "test" )
// Verify that a ClusterIP Service has been created.
name := findGenNameForEgressSvcResources ( t , fc , svc )
expectEqual ( t , fc , clusterIPSvc ( name , svc ) , removeTargetPortsFromSvc )
clusterSvc := mustGetClusterIPSvc ( t , fc , name )
// Verify that an EndpointSlice has been created.
expectEqual ( t , fc , endpointSlice ( name , svc , clusterSvc ) , nil )
// Verify that ConfigMap contains configuration for the new egress service.
mustHaveConfigForSvc ( t , fc , svc , clusterSvc , cm )
r := svcConfiguredReason ( svc , true , zl . Sugar ( ) )
// Verify that the user-created ExternalName Service has Configured set to true and ExternalName pointing to the
// CluterIP Service.
svc . Status . Conditions = [ ] metav1 . Condition {
condition ( tsapi . EgressSvcValid , metav1 . ConditionTrue , "EgressSvcValid" , "EgressSvcValid" , clock ) ,
condition ( tsapi . EgressSvcConfigured , metav1 . ConditionTrue , r , r , clock ) ,
}
svc . ObjectMeta . Finalizers = [ ] string { "tailscale.com/finalizer" }
svc . Spec . ExternalName = fmt . Sprintf ( "%s.operator-ns.svc.cluster.local" , name )
expectEqual ( t , fc , svc , nil )
}
func condition ( typ tsapi . ConditionType , st metav1 . ConditionStatus , r , msg string , clock tstime . Clock ) metav1 . Condition {
return metav1 . Condition {
Type : string ( typ ) ,