@ -105,10 +105,57 @@ 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" )
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 ) {
name := findGenNameForEgressSvcResources ( t , fc , svc )
if err := fc . Delete ( context . Background ( ) , svc ) ; err != nil {
t . Fatalf ( "error deleting ExternalName Service: %v" , err )
}
expectReconciled ( t , esr , "default" , "test" )
// Verify that ClusterIP Service and EndpointSlice have been deleted.
expectMissing [ corev1 . Service ] ( t , fc , "operator-ns" , name )
expectMissing [ discoveryv1 . EndpointSlice ] ( t , fc , "operator-ns" , fmt . Sprintf ( "%s-ipv4" , name ) )
// Verify that service config has been deleted from the ConfigMap.
mustNotHaveConfigForSvc ( t , fc , svc , cm )
} )
}
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 )
@ -122,25 +169,13 @@ func TestTailscaleEgressServices(t *testing.T) {
// 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 )
} )
t . Run ( "delete_external_name_service" , func ( t * testing . T ) {
name := findGenNameForEgressSvcResources ( t , fc , svc )
if err := fc . Delete ( context . Background ( ) , svc ) ; err != nil {
t . Fatalf ( "error deleting ExternalName Service: %v" , err )
}
expectReconciled ( t , esr , "default" , "test" )
// Verify that ClusterIP Service and EndpointSlice have been deleted.
expectMissing [ corev1 . Service ] ( t , fc , "operator-ns" , name )
expectMissing [ discoveryv1 . EndpointSlice ] ( t , fc , "operator-ns" , fmt . Sprintf ( "%s-ipv4" , name ) )
// Verify that service config has been deleted from the ConfigMap.
mustNotHaveConfigForSvc ( t , fc , svc , cm )
} )
}
func condition ( typ tsapi . ConditionType , st metav1 . ConditionStatus , r , msg string , clock tstime . Clock ) metav1 . Condition {