@@ -739,3 +739,103 @@ spec:
739739 t .Fatalf ("Failed to wait for object to be synced down: %v" , err )
740740 }
741741}
742+
743+ func TestSyncWithWorkspacePath (t * testing.T ) {
744+ const (
745+ apiExportName = "kcp.example.com"
746+ kcpGroupName = "kcp.example.com"
747+ orgWorkspace = "sync-with-paths"
748+ )
749+
750+ ctx := t .Context ()
751+ ctrlruntime .SetLogger (logr .Discard ())
752+
753+ // setup a test environment in kcp
754+ orgKubconfig := utils .CreateOrganization (t , ctx , orgWorkspace , apiExportName )
755+
756+ // start a service cluster
757+ envtestKubeconfig , envtestClient , _ := utils .RunEnvtest (t , []string {
758+ "test/crds/crontab.yaml" ,
759+ })
760+
761+ // publish Crontabs and Backups
762+ t .Logf ("Publishing CRDs…" )
763+ prCrontabs := & syncagentv1alpha1.PublishedResource {
764+ ObjectMeta : metav1.ObjectMeta {
765+ Name : "publish-crontabs" ,
766+ },
767+ Spec : syncagentv1alpha1.PublishedResourceSpec {
768+ Resource : syncagentv1alpha1.SourceResourceDescriptor {
769+ APIGroup : "example.com" ,
770+ Version : "v1" ,
771+ Kind : "CronTab" ,
772+ },
773+ // These rules make finding the local object easier, but should not be used in production.
774+ Naming : & syncagentv1alpha1.ResourceNaming {
775+ Name : "{{ .Object.metadata.name }}" ,
776+ Namespace : "synced-{{ .Object.metadata.namespace }}" ,
777+ },
778+ Projection : & syncagentv1alpha1.ResourceProjection {
779+ Group : kcpGroupName ,
780+ },
781+ EnableWorkspacePaths : true ,
782+ },
783+ }
784+
785+ if err := envtestClient .Create (ctx , prCrontabs ); err != nil {
786+ t .Fatalf ("Failed to create PublishedResource: %v" , err )
787+ }
788+
789+ // start the agent in the background to update the APIExport with the CronTabs API
790+ utils .RunAgent (ctx , t , "bob" , orgKubconfig , envtestKubeconfig , apiExportName )
791+
792+ // wait until the API is available
793+ kcpClusterClient := utils .GetKcpAdminClusterClient (t )
794+
795+ teamClusterPath := logicalcluster .NewPath ("root" ).Join (orgWorkspace ).Join ("team-1" )
796+ teamClient := kcpClusterClient .Cluster (teamClusterPath )
797+
798+ utils .WaitForBoundAPI (t , ctx , teamClient , schema.GroupVersionResource {
799+ Group : kcpGroupName ,
800+ Version : "v1" ,
801+ Resource : "crontabs" ,
802+ })
803+
804+ // create a Crontab object in a team workspace
805+ t .Log ("Creating CronTab in kcp…" )
806+ crontab := utils .YAMLToUnstructured (t , `
807+ apiVersion: kcp.example.com/v1
808+ kind: CronTab
809+ metadata:
810+ namespace: default
811+ name: my-crontab
812+ spec:
813+ cronSpec: '* * *'
814+ image: ubuntu:latest
815+ ` )
816+
817+ if err := teamClient .Create (ctx , crontab ); err != nil {
818+ t .Fatalf ("Failed to create CronTab in kcp: %v" , err )
819+ }
820+
821+ // wait for the agent to sync the object down into the service cluster
822+
823+ t .Logf ("Wait for CronTab to be synced…" )
824+ copy := & unstructured.Unstructured {}
825+ copy .SetAPIVersion ("example.com/v1" )
826+ copy .SetKind ("CronTab" )
827+
828+ err := wait .PollUntilContextTimeout (ctx , 500 * time .Millisecond , 30 * time .Second , false , func (ctx context.Context ) (done bool , err error ) {
829+ copyKey := types.NamespacedName {Namespace : "synced-default" , Name : "my-crontab" }
830+ return envtestClient .Get (ctx , copyKey , copy ) == nil , nil
831+ })
832+ if err != nil {
833+ t .Fatalf ("Failed to wait for object to be synced down: %v" , err )
834+ }
835+
836+ ann := "syncagent.kcp.io/remote-object-workspace-path"
837+
838+ if value := copy .GetAnnotations ()[ann ]; value != teamClusterPath .String () {
839+ t .Fatalf ("Expected %s annotation to be %q, but is %q." , ann , teamClusterPath .String (), value )
840+ }
841+ }
0 commit comments