Repository: submariner-io/lighthouse
Pull request #357 (2020-10-29 13:25:32)

Use the MCS APIs instead of our own
Fixes: /submariner-io/lighthouse#336

Signed-off-by: Aswin Surayanarayanan <asuryana@redhat.com>
Co-authored-by: Stephen Kitt <skitt@redhat.com>

submariner-bot: 🤖 Created branch: z_pr357/aswinsuryan/use-mcs-api
nyechiel: @aswinsuryan @skitt can we close https://github.com/submariner-io/lighthouse/pull/334 at this point?
skitt: > @aswinsuryan @skitt can we close #334 at this point?

Done!
vthapar: As discussed in call, we need a controller to convert old ServiceExport to new ones till we have changes in operator and subctl available to avoid chicken-n-egg scenario
aswinsuryan: > As discussed in call, we need a controller to convert old ServiceExport to new ones till we have changes in operator and subctl available to avoid chicken-n-egg scenario

I have added the controller to convert Lighthouse ServiceImport to mcs ServiceImport
aswinsuryan: The operator build requires https://github.com/submariner-io/submariner-operator/pull/848 to pass

Patch:
diff --git a/go.mod b/go.mod
index 7248b12..59d253e 100644
--- a/go.mod
+++ b/go.mod
@@ -11,13 +11,14 @@ require (
 	github.com/onsi/gomega v1.10.3
 	github.com/pkg/errors v0.9.1
 	github.com/submariner-io/admiral v0.7.0
-	github.com/submariner-io/shipyard v0.7.2
-	k8s.io/api v0.17.2
-	k8s.io/apimachinery v0.17.2
+	github.com/submariner-io/shipyard v0.7.3-0.20201105165619-4a6063d2b38c
+	k8s.io/api v0.18.4
+	k8s.io/apimachinery v0.18.4
 	k8s.io/client-go v11.0.0+incompatible
 	k8s.io/klog v1.0.0
-	k8s.io/utils v0.0.0-20200520001619-278ece378a50
-	sigs.k8s.io/controller-runtime v0.3.0
+	k8s.io/utils v0.0.0-20200603063816-c1c6865ac451
+	sigs.k8s.io/controller-runtime v0.6.1
+	sigs.k8s.io/mcs-api v0.0.0-20200908023942-d26176718973
 )
 
 // Pinned to kubernetes-1.17.0
diff --git a/go.sum b/go.sum
index 2f4ca9a..e664f7e 100644
--- a/go.sum
+++ b/go.sum
@@ -47,6 +47,7 @@ github.com/DataDog/datadog-go v3.3.1+incompatible/go.mod h1:LButxg5PwREeZtORoXG3
 github.com/DataDog/zstd v1.3.5 h1:DtpNbljikUepEPD16hD4LvIcmhnhdLTiW/5pHgbmp14=
 github.com/DataDog/zstd v1.3.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
 github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
+github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
 github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
 github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
@@ -65,6 +66,7 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alessio/shellescape v1.2.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
 github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190808125512-07798873deee/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ=
 github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
 github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
@@ -92,6 +94,8 @@ github.com/caddyserver/caddy v1.0.5/go.mod h1:AnFHB+/MrgRC+mJAvuAgQ38ePzw+wKeW0w
 github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
 github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
@@ -103,6 +107,7 @@ github.com/coredns/coredns v1.6.7 h1:q3F5gAB/SPzE5uPjnP5Z5q5eTzWKzjK0rck9GyfrY1M
 github.com/coredns/coredns v1.6.7/go.mod h1:jGC7ZBgMf6n4LM4VMrgYbiNefNRH/hjyqCkXlngNykw=
 github.com/coredns/federation v0.0.0-20190818181423-e032b096babe h1:ND08lR/TclI9W4dScCwdRESOacCCdF3FkuB5pBIOv1U=
 github.com/coredns/federation v0.0.0-20190818181423-e032b096babe/go.mod h1:MoqTEFX8GlnKkyq8eBCF94VzkNAOgjdlCJ+Pz/oCLPk=
+github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
 github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
 github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
@@ -120,6 +125,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
 github.com/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMElOWxok=
 github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -128,6 +134,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 github.com/decker502/dnspod-go v0.2.0/go.mod h1:qsurYu1FgxcDwfSwXJdLt4kRsBLZeosEb9uq4Sy+08g=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4=
 github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
 github.com/dnaeon/go-vcr v0.0.0-20180814043457-aafff18a5cc2/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
@@ -162,6 +169,7 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
 github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
 github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
+github.com/evanphx/json-patch/v5 v5.0.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
 github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE=
 github.com/farsightsec/golang-framestream v0.0.0-20181102145529-8a0cb8ba8710 h1:QdyRyGZWLEvJG5Kw3VcVJvhXJ5tZ1MkRgqpJOEZSySM=
 github.com/farsightsec/golang-framestream v0.0.0-20181102145529-8a0cb8ba8710/go.mod h1:eNde4IQyEiA5br02AouhEHCu3p3UzrCdFR4LuQHklMI=
@@ -235,6 +243,7 @@ github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+
 github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
 github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gobuffalo/flect v0.2.0/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80=
 github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -246,7 +255,6 @@ github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptG
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -305,11 +313,13 @@ github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY
 github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
 github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
+github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
 github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg=
 github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
 github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
 github.com/grpc-ecosystem/grpc-gateway v1.9.5 h1:UImYN5qQ8tuGpGE16ZmjvcTtTw24zw1QAp/SlnNrZhI=
 github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
 github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU=
@@ -325,13 +335,15 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
 github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
-github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ=
 github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
+github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
+github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/infobloxopen/go-trees v0.0.0-20190313150506-2af4e13f9062 h1:d3VSuNcgTCn21dNMm8g412Fck/XWFmMj4nJhhHT7ZZ0=
 github.com/infobloxopen/go-trees v0.0.0-20190313150506-2af4e13f9062/go.mod h1:PcNJqIlcX/dj3DTG/+QQnRvSgTMG6CLpRMjWcv4+J6w=
+github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
 github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@@ -344,6 +356,8 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
 github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
 github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
@@ -382,8 +396,11 @@ github.com/marten-seemann/chacha20 v0.2.0/go.mod h1:HSdjFau7GzYRj+ahFNwsO3ouVJr1
 github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI=
 github.com/marten-seemann/qtls v0.4.1/go.mod h1:pxVXcHHw1pNIt8Qo0pwSYQEoZ8yYOOPXTCZLQQunvRc=
 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
 github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
 github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
 github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
 github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
@@ -420,22 +437,25 @@ github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2
 github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw=
 github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
 github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
+github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
 github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
 github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
 github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
 github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4=
 github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
 github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M=
 github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
 github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
-github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
 github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs=
@@ -453,6 +473,7 @@ github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukw
 github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ=
 github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
 github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
 github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
@@ -468,6 +489,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
 github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
+github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
 github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8=
 github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
@@ -481,7 +503,9 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
 github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
 github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo=
 github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
@@ -490,11 +514,15 @@ github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X
 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE=
 github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
 github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
 github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
+github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia5qI=
+github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA=
 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ=
 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
@@ -516,19 +544,21 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1
 github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
 github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
 github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
+github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
 github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
+github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
-github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
+github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
@@ -544,8 +574,8 @@ github.com/submariner-io/admiral v0.7.0 h1:1Ddjx8PvmeUjqO9+qMAPoFgkDSq8asmXl/tls
 github.com/submariner-io/admiral v0.7.0/go.mod h1:S5Aemqu4Ac2sZWW9AEfPIhSC4eMCWmCVQ/rSSEHRt2o=
 github.com/submariner-io/shipyard v0.7.1 h1:2+CdN9c7BZX7AUKvBrRkqvha+qqEfbWRjgutbFNaiKo=
 github.com/submariner-io/shipyard v0.7.1/go.mod h1:m2Gs15WS6bCDMY2QUjjeC3p4Q95H+pG2UW4k2S9rhQc=
-github.com/submariner-io/shipyard v0.7.2 h1:jlg8AHfBkAqWKJXyby1VEBN1aCipDgwfCvBoWr5Qb6M=
-github.com/submariner-io/shipyard v0.7.2/go.mod h1:m4Qj1bHIgQBmp/CoPQOhsQDaQJvaF9YV3oyDLNfecRg=
+github.com/submariner-io/shipyard v0.7.3-0.20201105165619-4a6063d2b38c h1:WuHXKffODH74STWiBjYLVOtnNPxuUhtec9ErkEW+j/M=
+github.com/submariner-io/shipyard v0.7.3-0.20201105165619-4a6063d2b38c/go.mod h1:m4Qj1bHIgQBmp/CoPQOhsQDaQJvaF9YV3oyDLNfecRg=
 github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
 github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY=
 github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU=
@@ -555,6 +585,7 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc
 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY=
 github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
+github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
@@ -566,6 +597,7 @@ github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4m
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
 go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
@@ -581,10 +613,11 @@ go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
 go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y=
-go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -637,6 +670,7 @@ golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -677,6 +711,7 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -695,6 +730,8 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
 golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -769,6 +806,7 @@ google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.23.1 h1:q4XQuHFC6I28BKZpo6IYyb3mNO+l7lSOxRuYTCiDfXk=
@@ -788,6 +826,7 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
@@ -813,6 +852,8 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo=
 gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@@ -837,7 +878,6 @@ k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8
 k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
 k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
-k8s.io/klog v0.3.3/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
 k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
 k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
 k8s.io/klog/v2 v2.0.0 h1:Foj74zO6RbjjP4hBEKjnYtjjAhGg4jNynUdYF6fJrok=
@@ -845,23 +885,26 @@ k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
 k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
 k8s.io/kube-openapi v0.0.0-20200204173128-addea2498afe h1:GOfbcWvX5wW2vcfNch83xYp9SDZjRgAJk+t373yaHKk=
 k8s.io/kube-openapi v0.0.0-20200204173128-addea2498afe/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
-k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
 k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
 k8s.io/utils v0.0.0-20200520001619-278ece378a50 h1:ZtTUW5+ZWaoqjR3zOpRa7oFJ5d4aA22l4me/xArfOIc=
 k8s.io/utils v0.0.0-20200520001619-278ece378a50/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
+k8s.io/utils v0.0.0-20200603063816-c1c6865ac451 h1:v8ud2Up6QK1lNOKFgiIVrZdMg7MpmSnvtrOieolJKoE=
+k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
 modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
 modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
 modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
 modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
-sigs.k8s.io/controller-runtime v0.3.0 h1:ZtdgqJXVHsIytjdmDuk0QjagnzyLq9FjojXRqIp+dU4=
-sigs.k8s.io/controller-runtime v0.3.0/go.mod h1:Cw6PkEg0Sa7dAYovGT4R0tRkGhHXpYijwNxYhAnAZZk=
+sigs.k8s.io/controller-runtime v0.6.1 h1:LcK2+nk0kmaOnKGN+vBcWHqY5WDJNJNB/c5pW+sU8fc=
+sigs.k8s.io/controller-runtime v0.6.1/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A=
+sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI=
+sigs.k8s.io/kind v0.8.1/go.mod h1:oNKTxUVPYkV9lWzY6CVMNluVq8cBsyq+UgPJdvA3uu4=
+sigs.k8s.io/mcs-api v0.0.0-20200908023942-d26176718973 h1:WMyup1v/JrXbDn/s8NCbj3YeUcLEk7OsNJYSyDczubY=
+sigs.k8s.io/mcs-api v0.0.0-20200908023942-d26176718973/go.mod h1:gGiAryeFNB4GBsq2LBmVqSgKoobLxt+p7ii/WG5QYYw=
 sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
 sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18=
 sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
-sigs.k8s.io/testing_frameworks v0.1.1 h1:cP2l8fkA3O9vekpy5Ks8mmA0NW/F7yBdXf8brkWhVrs=
-sigs.k8s.io/testing_frameworks v0.1.1/go.mod h1:VVBKrHmJ6Ekkfz284YKhQePcdycOzNH9qL6ht1zEr/U=
 sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
 sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
 sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
diff --git a/pkg/agent/controller/agent.go b/pkg/agent/controller/agent.go
index de8f9ba..2722451 100644
--- a/pkg/agent/controller/agent.go
+++ b/pkg/agent/controller/agent.go
@@ -9,7 +9,6 @@ import (
 	"github.com/submariner-io/admiral/pkg/syncer"
 	"github.com/submariner-io/admiral/pkg/syncer/broker"
 	"github.com/submariner-io/admiral/pkg/util"
-	lighthousev2a1 "github.com/submariner-io/lighthouse/pkg/apis/lighthouse.submariner.io/v2alpha1"
 	lhconstants "github.com/submariner-io/lighthouse/pkg/constants"
 	corev1 "k8s.io/api/core/v1"
 	discovery "k8s.io/api/discovery/v1beta1"
@@ -25,6 +24,7 @@ import (
 	"k8s.io/client-go/rest"
 	"k8s.io/client-go/util/retry"
 	"k8s.io/klog"
+	mcsv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
 )
 
 const (
@@ -71,7 +71,7 @@ func NewWithDetail(spec *AgentSpecification, syncerConf *broker.SyncerConfig, re
 		kubeClientSet:    kubeClientSet,
 	}
 
-	_, gvr, err := util.ToUnstructuredResource(&lighthousev2a1.ServiceExport{}, restMapper)
+	_, gvr, err := util.ToUnstructuredResource(&mcsv1a1.ServiceExport{}, restMapper)
 	if err != nil {
 		return nil, err
 	}
@@ -80,10 +80,10 @@ func NewWithDetail(spec *AgentSpecification, syncerConf *broker.SyncerConfig, re
 
 	svcExportResourceConfig := broker.ResourceConfig{
 		LocalSourceNamespace:  metav1.NamespaceAll,
-		LocalResourceType:     &lighthousev2a1.ServiceExport{},
+		LocalResourceType:     &mcsv1a1.ServiceExport{},
 		LocalTransform:        agentController.serviceExportToRemoteServiceImport,
 		LocalOnSuccessfulSync: agentController.onSuccessfulServiceImportSync,
-		BrokerResourceType:    &lighthousev2a1.ServiceImport{},
+		BrokerResourceType:    &mcsv1a1.ServiceImport{},
 	}
 
 	syncerConf.Scheme = runtimeScheme
@@ -146,6 +146,12 @@ func NewWithDetail(spec *AgentSpecification, syncerConf *broker.SyncerConfig, re
 		return nil, err
 	}
 
+	agentController.lhServiceExportController, err = newLHServiceExportController(localClient, restMapper, runtimeScheme)
+
+	if err != nil {
+		return nil, err
+	}
+
 	return agentController, nil
 }
 
@@ -174,6 +180,10 @@ func (a *Controller) Start(stopCh <-chan struct{}) error {
 		return err
 	}
 
+	if err := a.lhServiceExportController.start(stopCh); err != nil {
+		return err
+	}
+
 	klog.Info("Agent controller started")
 
 	return nil
@@ -184,7 +194,7 @@ func (a *Controller) serviceExportToRemoteServiceImport(obj runtime.Object, op s
 		return nil, false
 	}
 
-	svcExport := obj.(*lighthousev2a1.ServiceExport)
+	svcExport := obj.(*mcsv1a1.ServiceExport)
 	serviceImport := a.newServiceImport(svcExport)
 
 	if op == syncer.Delete {
@@ -194,7 +204,7 @@ func (a *Controller) serviceExportToRemoteServiceImport(obj runtime.Object, op s
 	obj, found, err := a.serviceSyncer.GetResource(svcExport.Name, svcExport.Namespace)
 	if err != nil {
 		// some other error. Log and requeue
-		a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, lighthousev2a1.ServiceExportInitialized,
+		a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, mcsv1a1.ServiceExportValid,
 			corev1.ConditionUnknown, "ServiceRetrievalFailed", fmt.Sprintf("Error retrieving the Service: %v", err))
 		klog.Errorf("Error retrieving Service (%s/%s): %v", svcExport.Namespace, svcExport.Name, err)
 
@@ -203,7 +213,7 @@ func (a *Controller) serviceExportToRemoteServiceImport(obj runtime.Object, op s
 
 	if !found {
 		klog.V(log.DEBUG).Infof("Service to be exported (%s/%s) doesn't exist", svcExport.Namespace, svcExport.Name)
-		a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, lighthousev2a1.ServiceExportInitialized,
+		a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, mcsv1a1.ServiceExportValid,
 			corev1.ConditionFalse, serviceUnavailable, "Service to be exported doesn't exist")
 
 		return nil, true
@@ -214,16 +224,16 @@ func (a *Controller) serviceExportToRemoteServiceImport(obj runtime.Object, op s
 	svcType, ok := getServiceImportType(svc)
 
 	if !ok {
-		a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, lighthousev2a1.ServiceExportInitialized,
+		a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, mcsv1a1.ServiceExportValid,
 			corev1.ConditionFalse, invalidServiceType, fmt.Sprintf("Service of type %v not supported", svc.Spec.Type))
 		klog.Errorf("Service type %q not supported", svc.Spec.Type)
 
 		return nil, false
 	}
 
-	if a.globalnetEnabled && svcType == lighthousev2a1.Headless {
+	if a.globalnetEnabled && svcType == mcsv1a1.Headless {
 		klog.Infof("Headless Services not supported with globalnet yet")
-		a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, lighthousev2a1.ServiceExportInitialized,
+		a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, mcsv1a1.ServiceExportValid,
 			corev1.ConditionFalse, invalidServiceType, "Headless Services not supported with Globalnet IP")
 
 		return nil, false
@@ -233,14 +243,14 @@ func (a *Controller) serviceExportToRemoteServiceImport(obj runtime.Object, op s
 		klog.V(log.DEBUG).Infof("Service to be exported (%s/%s) doesn't have a global IP yet", svcExport.Namespace, svcExport.Name)
 
 		// Globalnet enabled but service doesn't have globalIp yet, Update the status and requeue
-		a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, lighthousev2a1.ServiceExportInitialized,
+		a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, mcsv1a1.ServiceExportValid,
 			corev1.ConditionFalse, "ServiceGlobalIPUnavailable", "Service doesn't have a global IP yet")
 
 		return nil, true
 	}
 
-	serviceImport.Spec = lighthousev2a1.ServiceImportSpec{
-		Ports:                 []lighthousev2a1.ServicePort{},
+	serviceImport.Spec = mcsv1a1.ServiceImportSpec{
+		Ports:                 []mcsv1a1.ServicePort{},
 		Type:                  svcType,
 		SessionAffinityConfig: new(corev1.SessionAffinityConfig),
 	}
@@ -248,44 +258,44 @@ func (a *Controller) serviceExportToRemoteServiceImport(obj runtime.Object, op s
 	ips, err := a.getIPsForService(svc, svcType)
 	if err != nil {
 		// Failed to get ips for some reason, requeue
-		a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, lighthousev2a1.ServiceExportInitialized,
+		a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, mcsv1a1.ServiceExportValid,
 			corev1.ConditionUnknown, "ServiceRetrievalFailed", err.Error())
 
 		return nil, true
 	}
 
-	serviceImport.Status = lighthousev2a1.ServiceImportStatus{
-		Clusters: []lighthousev2a1.ClusterStatus{
+	serviceImport.Status = mcsv1a1.ServiceImportStatus{
+		Clusters: []mcsv1a1.ClusterStatus{
 			{
 				Cluster: a.clusterID,
 			},
 		},
 	}
 
-	if svcType == lighthousev2a1.ClusterSetIP {
-		serviceImport.Spec.IP = ips[0]
+	if svcType == mcsv1a1.ClusterSetIP {
+		serviceImport.Spec.IPs = ips
 		/* We also store the clusterIP in an annotation as an optimization to recover it in case the IPs are
 		cleared out when here's no backing Endpoint pods.
 		*/
 		serviceImport.Annotations[clusterIP] = ips[0]
 	}
 
-	a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, lighthousev2a1.ServiceExportInitialized,
+	a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, mcsv1a1.ServiceExportValid,
 		corev1.ConditionTrue, "AwaitingSync", "Awaiting sync of the ServiceImport to the broker")
 
 	return serviceImport, false
 }
 
-func getServiceImportType(service *corev1.Service) (lighthousev2a1.ServiceImportType, bool) {
+func getServiceImportType(service *corev1.Service) (mcsv1a1.ServiceImportType, bool) {
 	if service.Spec.Type != "" && service.Spec.Type != corev1.ServiceTypeClusterIP {
 		return "", false
 	}
 
 	if service.Spec.ClusterIP == corev1.ClusterIPNone {
-		return lighthousev2a1.Headless, true
+		return mcsv1a1.Headless, true
 	}
 
-	return lighthousev2a1.ClusterSetIP, true
+	return mcsv1a1.ClusterSetIP, true
 }
 
 func (a *Controller) onSuccessfulServiceImportSync(synced runtime.Object, op syncer.Operation) {
@@ -293,11 +303,11 @@ func (a *Controller) onSuccessfulServiceImportSync(synced runtime.Object, op syn
 		return
 	}
 
-	serviceImport := synced.(*lighthousev2a1.ServiceImport)
+	serviceImport := synced.(*mcsv1a1.ServiceImport)
 
 	a.updateExportedServiceStatus(serviceImport.GetAnnotations()[lhconstants.OriginName],
 		serviceImport.GetAnnotations()[lhconstants.OriginNamespace],
-		lighthousev2a1.ServiceExportExported, corev1.ConditionTrue,
+		mcsv1a1.ServiceExportValid, corev1.ConditionTrue,
 		"", "Service was successfully synced to the broker")
 }
 
@@ -308,7 +318,7 @@ func (a *Controller) serviceToRemoteServiceImport(obj runtime.Object, op syncer.
 	}
 
 	svc := obj.(*corev1.Service)
-	obj, found, err := a.serviceExportSyncer.GetLocalResource(svc.Name, svc.Namespace, &lighthousev2a1.ServiceExport{})
+	obj, found, err := a.serviceExportSyncer.GetLocalResource(svc.Name, svc.Namespace, &mcsv1a1.ServiceExport{})
 	if err != nil {
 		// some other error. Log and requeue
 		klog.Errorf("Error retrieving ServiceExport for Service (%s/%s): %v", svc.Namespace, svc.Name, err)
@@ -320,18 +330,18 @@ func (a *Controller) serviceToRemoteServiceImport(obj runtime.Object, op syncer.
 		return nil, false
 	}
 
-	svcExport := obj.(*lighthousev2a1.ServiceExport)
+	svcExport := obj.(*mcsv1a1.ServiceExport)
 
 	serviceImport := a.newServiceImport(svcExport)
 
 	// Update the status and requeue
-	a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, lighthousev2a1.ServiceExportInitialized,
+	a.updateExportedServiceStatus(svcExport.Name, svcExport.Namespace, mcsv1a1.ServiceExportValid,
 		corev1.ConditionFalse, serviceUnavailable, "Service to be exported doesn't exist")
 
 	return serviceImport, false
 }
 
-func (a *Controller) updateExportedServiceStatus(name, namespace string, condType lighthousev2a1.ServiceExportConditionType,
+func (a *Controller) updateExportedServiceStatus(name, namespace string, condType mcsv1a1.ServiceExportConditionType,
 	status corev1.ConditionStatus, reason, msg string) {
 	retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
 		toUpdate, err := a.getServiceExport(name, namespace)
@@ -343,7 +353,7 @@ func (a *Controller) updateExportedServiceStatus(name, namespace string, condTyp
 		}
 
 		now := metav1.Now()
-		exportCondition := lighthousev2a1.ServiceExportCondition{
+		exportCondition := mcsv1a1.ServiceExportCondition{
 			Type:               condType,
 			Status:             status,
 			LastTransitionTime: &now,
@@ -371,7 +381,7 @@ func (a *Controller) updateExportedServiceStatus(name, namespace string, condTyp
 			return err
 		}
 
-		_, err = a.serviceExportClient.Namespace(toUpdate.Namespace).Update(raw, metav1.UpdateOptions{})
+		_, err = a.serviceExportClient.Namespace(toUpdate.Namespace).UpdateStatus(raw, metav1.UpdateOptions{})
 
 		return err
 	})
@@ -380,13 +390,13 @@ func (a *Controller) updateExportedServiceStatus(name, namespace string, condTyp
 	}
 }
 
-func (a *Controller) getServiceExport(name, namespace string) (*lighthousev2a1.ServiceExport, error) {
+func (a *Controller) getServiceExport(name, namespace string) (*mcsv1a1.ServiceExport, error) {
 	obj, err := a.serviceExportClient.Namespace(namespace).Get(name, metav1.GetOptions{})
 	if err != nil {
 		return nil, err
 	}
 
-	se := &lighthousev2a1.ServiceExport{}
+	se := &mcsv1a1.ServiceExport{}
 	err = a.serviceImportController.scheme.Convert(obj, se, nil)
 	if err != nil {
 		return nil, errors.WithMessagef(err, "Error converting %#v to ServiceExport", obj)
@@ -395,13 +405,13 @@ func (a *Controller) getServiceExport(name, namespace string) (*lighthousev2a1.S
 	return se, nil
 }
 
-func serviceExportConditionEqual(c1, c2 *lighthousev2a1.ServiceExportCondition) bool {
+func serviceExportConditionEqual(c1, c2 *mcsv1a1.ServiceExportCondition) bool {
 	return c1.Type == c2.Type && c1.Status == c2.Status && reflect.DeepEqual(c1.Reason, c2.Reason) &&
 		reflect.DeepEqual(c1.Message, c2.Message)
 }
 
-func (a *Controller) newServiceImport(svcExport *lighthousev2a1.ServiceExport) *lighthousev2a1.ServiceImport {
-	return &lighthousev2a1.ServiceImport{
+func (a *Controller) newServiceImport(svcExport *mcsv1a1.ServiceExport) *mcsv1a1.ServiceImport {
+	return &mcsv1a1.ServiceImport{
 		ObjectMeta: metav1.ObjectMeta{
 			Name: a.getObjectNameWithClusterId(svcExport.Name, svcExport.Namespace),
 			Annotations: map[string]string{
@@ -417,8 +427,8 @@ func (a *Controller) newServiceImport(svcExport *lighthousev2a1.ServiceExport) *
 	}
 }
 
-func (a *Controller) getIPsForService(service *corev1.Service, siType lighthousev2a1.ServiceImportType) ([]string, error) {
-	if siType == lighthousev2a1.ClusterSetIP {
+func (a *Controller) getIPsForService(service *corev1.Service, siType mcsv1a1.ServiceImportType) ([]string, error) {
+	if siType == mcsv1a1.ClusterSetIP {
 		mcsIp := getGlobalIpFromService(service)
 		if mcsIp == "" {
 			mcsIp = service.Spec.ClusterIP
diff --git a/pkg/agent/controller/lhserviceexport.go b/pkg/agent/controller/lhserviceexport.go
new file mode 100644
index 0000000..ac4d0f4
--- /dev/null
+++ b/pkg/agent/controller/lhserviceexport.go
@@ -0,0 +1,78 @@
+package controller
+
+import (
+	"github.com/submariner-io/admiral/pkg/syncer"
+	"github.com/submariner-io/admiral/pkg/syncer/broker"
+	lighthousev2a1 "github.com/submariner-io/lighthouse/pkg/apis/lighthouse.submariner.io/v2alpha1"
+	"k8s.io/apimachinery/pkg/api/meta"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/client-go/dynamic"
+	"k8s.io/klog"
+	mcsv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
+)
+
+func newLHServiceExportController(localClient dynamic.Interface, restMapper meta.RESTMapper,
+	scheme *runtime.Scheme) (*LHServiceExportController, error) {
+	serviceExportController := LHServiceExportController{
+		localClient: localClient,
+	}
+
+	lhServiceExportSyncer, err := syncer.NewResourceSyncer(&syncer.ResourceSyncerConfig{
+		Name:             "lhServiceExport -> mcsServiceExport",
+		SourceClient:     localClient,
+		SourceNamespace:  metav1.NamespaceAll,
+		Direction:        syncer.LocalToRemote,
+		RestMapper:       restMapper,
+		Federator:        broker.NewFederator(localClient, restMapper, metav1.NamespaceAll, ""),
+		ResourceType:     &lighthousev2a1.ServiceExport{},
+		Transform:        serviceExportController.LHtoMCSServiceExport,
+		Scheme:           scheme,
+		OnSuccessfulSync: serviceExportController.deleteLHServiceExport,
+	})
+
+	if err != nil {
+		return nil, err
+	}
+
+	serviceExportController.lhServiceExportSyncer = lhServiceExportSyncer
+
+	return &serviceExportController, nil
+}
+
+func (c *LHServiceExportController) start(stopCh <-chan struct{}) error {
+	if err := c.lhServiceExportSyncer.Start(stopCh); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (c *LHServiceExportController) LHtoMCSServiceExport(obj runtime.Object, op syncer.Operation) (runtime.Object, bool) {
+	if op != syncer.Create {
+		return nil, false
+	}
+
+	serviceExportCreated := obj.(*lighthousev2a1.ServiceExport)
+	objMeta := serviceExportCreated.GetObjectMeta()
+	mcsServiceExport := &mcsv1a1.ServiceExport{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      objMeta.GetName(),
+			Namespace: objMeta.GetNamespace(),
+		},
+	}
+
+	return mcsServiceExport, false
+}
+
+func (c *LHServiceExportController) deleteLHServiceExport(obj runtime.Object, op syncer.Operation) {
+	serviceExportDeleted := obj.(*mcsv1a1.ServiceExport)
+	resourceClient := c.localClient.Resource(schema.GroupVersionResource{Group: "lighthouse.submariner.io",
+		Version: "v2alpha1", Resource: "serviceexports"}).Namespace(serviceExportDeleted.ObjectMeta.GetNamespace())
+	err := resourceClient.Delete(serviceExportDeleted.ObjectMeta.GetName(), &metav1.DeleteOptions{})
+
+	if err != nil {
+		klog.Errorf("Error deleting the ServiceExport %q: %v", serviceExportDeleted.GetObjectMeta().GetName(), err)
+	}
+}
diff --git a/pkg/agent/controller/serviceimport.go b/pkg/agent/controller/serviceimport.go
index 038da93..8f7f5aa 100644
--- a/pkg/agent/controller/serviceimport.go
+++ b/pkg/agent/controller/serviceimport.go
@@ -4,7 +4,6 @@ import (
 	"github.com/submariner-io/admiral/pkg/federate"
 	"github.com/submariner-io/admiral/pkg/log"
 	"github.com/submariner-io/admiral/pkg/syncer"
-	lighthousev2a1 "github.com/submariner-io/lighthouse/pkg/apis/lighthouse.submariner.io/v2alpha1"
 	lhconstants "github.com/submariner-io/lighthouse/pkg/constants"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/meta"
@@ -12,6 +11,7 @@ import (
 	"k8s.io/client-go/dynamic"
 	"k8s.io/client-go/tools/cache"
 	"k8s.io/klog"
+	mcsv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
 )
 
 func newServiceImportController(spec *AgentSpecification, serviceSyncer syncer.Interface, restMapper meta.RESTMapper,
@@ -33,7 +33,7 @@ func newServiceImportController(spec *AgentSpecification, serviceSyncer syncer.I
 		Direction:       syncer.LocalToRemote,
 		RestMapper:      restMapper,
 		Federator:       federate.NewNoopFederator(),
-		ResourceType:    &lighthousev2a1.ServiceImport{},
+		ResourceType:    &mcsv1a1.ServiceImport{},
 		Transform:       controller.serviceImportToEndpointController,
 		Scheme:          scheme,
 	})
@@ -63,7 +63,7 @@ func (c *ServiceImportController) start(stopCh <-chan struct{}) error {
 	return nil
 }
 
-func (c *ServiceImportController) serviceImportCreatedOrUpdated(serviceImport *lighthousev2a1.ServiceImport, key string) bool {
+func (c *ServiceImportController) serviceImportCreatedOrUpdated(serviceImport *mcsv1a1.ServiceImport, key string) bool {
 	if _, found := c.endpointControllers.Load(key); found {
 		klog.V(log.DEBUG).Infof("The endpoint controller is already running for %q", key)
 		return false
@@ -106,7 +106,7 @@ func (c *ServiceImportController) serviceImportCreatedOrUpdated(serviceImport *l
 	return false
 }
 
-func (c *ServiceImportController) serviceImportDeleted(serviceImport *lighthousev2a1.ServiceImport, key string) bool {
+func (c *ServiceImportController) serviceImportDeleted(serviceImport *mcsv1a1.ServiceImport, key string) bool {
 	if serviceImport.GetLabels()[lhconstants.LabelSourceCluster] != c.clusterID {
 		return false
 	}
@@ -121,7 +121,7 @@ func (c *ServiceImportController) serviceImportDeleted(serviceImport *lighthouse
 }
 
 func (c *ServiceImportController) serviceImportToEndpointController(obj runtime.Object, op syncer.Operation) (runtime.Object, bool) {
-	serviceImport := obj.(*lighthousev2a1.ServiceImport)
+	serviceImport := obj.(*mcsv1a1.ServiceImport)
 	key, _ := cache.MetaNamespaceKeyFunc(serviceImport)
 	if op == syncer.Create || op == syncer.Update {
 		return nil, c.serviceImportCreatedOrUpdated(serviceImport, key)
diff --git a/pkg/agent/controller/types.go b/pkg/agent/controller/types.go
index 3ed964c..ecbec4d 100644
--- a/pkg/agent/controller/types.go
+++ b/pkg/agent/controller/types.go
@@ -3,25 +3,27 @@ package controller
 import (
 	"sync"
 
+	"k8s.io/client-go/kubernetes"
+
 	"github.com/submariner-io/admiral/pkg/syncer"
 	"github.com/submariner-io/admiral/pkg/syncer/broker"
 	"k8s.io/apimachinery/pkg/api/meta"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/client-go/dynamic"
-	"k8s.io/client-go/kubernetes"
 )
 
 type Controller struct {
-	clusterID               string
-	globalnetEnabled        bool
-	namespace               string
-	kubeClientSet           kubernetes.Interface
-	serviceExportClient     dynamic.NamespaceableResourceInterface
-	serviceExportSyncer     *broker.Syncer
-	endpointSliceSyncer     *broker.Syncer
-	serviceSyncer           syncer.Interface
-	serviceImportController *ServiceImportController
+	clusterID                 string
+	globalnetEnabled          bool
+	namespace                 string
+	kubeClientSet             kubernetes.Interface
+	serviceExportClient       dynamic.NamespaceableResourceInterface
+	serviceExportSyncer       *broker.Syncer
+	endpointSliceSyncer       *broker.Syncer
+	serviceSyncer             syncer.Interface
+	serviceImportController   *ServiceImportController
+	lhServiceExportController *LHServiceExportController
 }
 
 type AgentSpecification struct {
@@ -54,3 +56,8 @@ type EndpointController struct {
 	serviceImportSourceNameSpace string
 	stopCh                       chan struct{}
 }
+
+type LHServiceExportController struct {
+	lhServiceExportSyncer syncer.Interface
+	localClient           dynamic.Interface
+}
diff --git a/pkg/agent/main.go b/pkg/agent/main.go
index 4ddb4c3..882c4a9 100644
--- a/pkg/agent/main.go
+++ b/pkg/agent/main.go
@@ -5,13 +5,13 @@ import (
 
 	"github.com/kelseyhightower/envconfig"
 	"github.com/submariner-io/lighthouse/pkg/agent/controller"
-	lighthousev1 "github.com/submariner-io/lighthouse/pkg/apis/lighthouse.submariner.io/v1"
-	lighthousev2a1 "github.com/submariner-io/lighthouse/pkg/apis/lighthouse.submariner.io/v2alpha1"
 	"k8s.io/client-go/kubernetes/scheme"
 
+	lighthousev2a1 "github.com/submariner-io/lighthouse/pkg/apis/lighthouse.submariner.io/v2alpha1"
 	"k8s.io/client-go/tools/clientcmd"
 	"k8s.io/klog"
 	"sigs.k8s.io/controller-runtime/pkg/manager/signals"
+	mcsv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
 )
 
 var (
@@ -33,9 +33,9 @@ func main() {
 
 	klog.Infof("AgentSpec: %v", agentSpec)
 
-	err = lighthousev1.AddToScheme(scheme.Scheme)
+	err = mcsv1a1.AddToScheme(scheme.Scheme)
 	if err != nil {
-		klog.Exitf("Error adding lighthouse V1 to the scheme: %v", err)
+		klog.Exitf("Error adding Multicluster v1alpha1 to the scheme: %v", err)
 	}
 
 	err = lighthousev2a1.AddToScheme(scheme.Scheme)
diff --git a/pkg/mcs/client/clientset/versioned/clientset.go b/pkg/mcs/client/clientset/versioned/clientset.go
new file mode 100644
index 0000000..5150c33
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/clientset.go
@@ -0,0 +1,97 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package versioned
+
+import (
+	"fmt"
+
+	multiclusterv1alpha1 "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1"
+	discovery "k8s.io/client-go/discovery"
+	rest "k8s.io/client-go/rest"
+	flowcontrol "k8s.io/client-go/util/flowcontrol"
+)
+
+type Interface interface {
+	Discovery() discovery.DiscoveryInterface
+	MulticlusterV1alpha1() multiclusterv1alpha1.MulticlusterV1alpha1Interface
+}
+
+// Clientset contains the clients for groups. Each group has exactly one
+// version included in a Clientset.
+type Clientset struct {
+	*discovery.DiscoveryClient
+	multiclusterV1alpha1 *multiclusterv1alpha1.MulticlusterV1alpha1Client
+}
+
+// MulticlusterV1alpha1 retrieves the MulticlusterV1alpha1Client
+func (c *Clientset) MulticlusterV1alpha1() multiclusterv1alpha1.MulticlusterV1alpha1Interface {
+	return c.multiclusterV1alpha1
+}
+
+// Discovery retrieves the DiscoveryClient
+func (c *Clientset) Discovery() discovery.DiscoveryInterface {
+	if c == nil {
+		return nil
+	}
+	return c.DiscoveryClient
+}
+
+// NewForConfig creates a new Clientset for the given config.
+// If config's RateLimiter is not set and QPS and Burst are acceptable,
+// NewForConfig will generate a rate-limiter in configShallowCopy.
+func NewForConfig(c *rest.Config) (*Clientset, error) {
+	configShallowCopy := *c
+	if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
+		if configShallowCopy.Burst <= 0 {
+			return nil, fmt.Errorf("Burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
+		}
+		configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
+	}
+	var cs Clientset
+	var err error
+	cs.multiclusterV1alpha1, err = multiclusterv1alpha1.NewForConfig(&configShallowCopy)
+	if err != nil {
+		return nil, err
+	}
+
+	cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
+	if err != nil {
+		return nil, err
+	}
+	return &cs, nil
+}
+
+// NewForConfigOrDie creates a new Clientset for the given config and
+// panics if there is an error in the config.
+func NewForConfigOrDie(c *rest.Config) *Clientset {
+	var cs Clientset
+	cs.multiclusterV1alpha1 = multiclusterv1alpha1.NewForConfigOrDie(c)
+
+	cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
+	return &cs
+}
+
+// New creates a new Clientset for the given RESTClient.
+func New(c rest.Interface) *Clientset {
+	var cs Clientset
+	cs.multiclusterV1alpha1 = multiclusterv1alpha1.New(c)
+
+	cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
+	return &cs
+}
diff --git a/pkg/mcs/client/clientset/versioned/doc.go b/pkg/mcs/client/clientset/versioned/doc.go
new file mode 100644
index 0000000..41721ca
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// This package has the automatically generated clientset.
+package versioned
diff --git a/pkg/mcs/client/clientset/versioned/fake/clientset_generated.go b/pkg/mcs/client/clientset/versioned/fake/clientset_generated.go
new file mode 100644
index 0000000..e2f8e21
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/fake/clientset_generated.go
@@ -0,0 +1,82 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	clientset "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned"
+	multiclusterv1alpha1 "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1"
+	fakemulticlusterv1alpha1 "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/fake"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/watch"
+	"k8s.io/client-go/discovery"
+	fakediscovery "k8s.io/client-go/discovery/fake"
+	"k8s.io/client-go/testing"
+)
+
+// NewSimpleClientset returns a clientset that will respond with the provided objects.
+// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
+// without applying any validations and/or defaults. It shouldn't be considered a replacement
+// for a real clientset and is mostly useful in simple unit tests.
+func NewSimpleClientset(objects ...runtime.Object) *Clientset {
+	o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
+	for _, obj := range objects {
+		if err := o.Add(obj); err != nil {
+			panic(err)
+		}
+	}
+
+	cs := &Clientset{tracker: o}
+	cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
+	cs.AddReactor("*", "*", testing.ObjectReaction(o))
+	cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
+		gvr := action.GetResource()
+		ns := action.GetNamespace()
+		watch, err := o.Watch(gvr, ns)
+		if err != nil {
+			return false, nil, err
+		}
+		return true, watch, nil
+	})
+
+	return cs
+}
+
+// Clientset implements clientset.Interface. Meant to be embedded into a
+// struct to get a default implementation. This makes faking out just the method
+// you want to test easier.
+type Clientset struct {
+	testing.Fake
+	discovery *fakediscovery.FakeDiscovery
+	tracker   testing.ObjectTracker
+}
+
+func (c *Clientset) Discovery() discovery.DiscoveryInterface {
+	return c.discovery
+}
+
+func (c *Clientset) Tracker() testing.ObjectTracker {
+	return c.tracker
+}
+
+var _ clientset.Interface = &Clientset{}
+
+// MulticlusterV1alpha1 retrieves the MulticlusterV1alpha1Client
+func (c *Clientset) MulticlusterV1alpha1() multiclusterv1alpha1.MulticlusterV1alpha1Interface {
+	return &fakemulticlusterv1alpha1.FakeMulticlusterV1alpha1{Fake: &c.Fake}
+}
diff --git a/pkg/mcs/client/clientset/versioned/fake/doc.go b/pkg/mcs/client/clientset/versioned/fake/doc.go
new file mode 100644
index 0000000..9b99e71
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// This package has the automatically generated fake clientset.
+package fake
diff --git a/pkg/mcs/client/clientset/versioned/fake/register.go b/pkg/mcs/client/clientset/versioned/fake/register.go
new file mode 100644
index 0000000..17bd0e1
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/fake/register.go
@@ -0,0 +1,56 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	serializer "k8s.io/apimachinery/pkg/runtime/serializer"
+	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
+	multiclusterv1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
+)
+
+var scheme = runtime.NewScheme()
+var codecs = serializer.NewCodecFactory(scheme)
+var parameterCodec = runtime.NewParameterCodec(scheme)
+var localSchemeBuilder = runtime.SchemeBuilder{
+	multiclusterv1alpha1.AddToScheme,
+}
+
+// AddToScheme adds all types of this clientset into the given scheme. This allows composition
+// of clientsets, like in:
+//
+//   import (
+//     "k8s.io/client-go/kubernetes"
+//     clientsetscheme "k8s.io/client-go/kubernetes/scheme"
+//     aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
+//   )
+//
+//   kclientset, _ := kubernetes.NewForConfig(c)
+//   _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
+//
+// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
+// correctly.
+var AddToScheme = localSchemeBuilder.AddToScheme
+
+func init() {
+	v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
+	utilruntime.Must(AddToScheme(scheme))
+}
diff --git a/pkg/mcs/client/clientset/versioned/scheme/doc.go b/pkg/mcs/client/clientset/versioned/scheme/doc.go
new file mode 100644
index 0000000..7dc3756
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/scheme/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// This package contains the scheme of the automatically generated clientset.
+package scheme
diff --git a/pkg/mcs/client/clientset/versioned/scheme/register.go b/pkg/mcs/client/clientset/versioned/scheme/register.go
new file mode 100644
index 0000000..4248e44
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/scheme/register.go
@@ -0,0 +1,56 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package scheme
+
+import (
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	serializer "k8s.io/apimachinery/pkg/runtime/serializer"
+	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
+	multiclusterv1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
+)
+
+var Scheme = runtime.NewScheme()
+var Codecs = serializer.NewCodecFactory(Scheme)
+var ParameterCodec = runtime.NewParameterCodec(Scheme)
+var localSchemeBuilder = runtime.SchemeBuilder{
+	multiclusterv1alpha1.AddToScheme,
+}
+
+// AddToScheme adds all types of this clientset into the given scheme. This allows composition
+// of clientsets, like in:
+//
+//   import (
+//     "k8s.io/client-go/kubernetes"
+//     clientsetscheme "k8s.io/client-go/kubernetes/scheme"
+//     aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
+//   )
+//
+//   kclientset, _ := kubernetes.NewForConfig(c)
+//   _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
+//
+// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
+// correctly.
+var AddToScheme = localSchemeBuilder.AddToScheme
+
+func init() {
+	v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
+	utilruntime.Must(AddToScheme(Scheme))
+}
diff --git a/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/apis_client.go b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/apis_client.go
new file mode 100644
index 0000000..bcd64df
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/apis_client.go
@@ -0,0 +1,94 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	"github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned/scheme"
+	rest "k8s.io/client-go/rest"
+	v1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
+)
+
+type MulticlusterV1alpha1Interface interface {
+	RESTClient() rest.Interface
+	ServiceExportsGetter
+	ServiceImportsGetter
+}
+
+// MulticlusterV1alpha1Client is used to interact with features provided by the multicluster.x-k8s.io group.
+type MulticlusterV1alpha1Client struct {
+	restClient rest.Interface
+}
+
+func (c *MulticlusterV1alpha1Client) ServiceExports(namespace string) ServiceExportInterface {
+	return newServiceExports(c, namespace)
+}
+
+func (c *MulticlusterV1alpha1Client) ServiceImports(namespace string) ServiceImportInterface {
+	return newServiceImports(c, namespace)
+}
+
+// NewForConfig creates a new MulticlusterV1alpha1Client for the given config.
+func NewForConfig(c *rest.Config) (*MulticlusterV1alpha1Client, error) {
+	config := *c
+	if err := setConfigDefaults(&config); err != nil {
+		return nil, err
+	}
+	client, err := rest.RESTClientFor(&config)
+	if err != nil {
+		return nil, err
+	}
+	return &MulticlusterV1alpha1Client{client}, nil
+}
+
+// NewForConfigOrDie creates a new MulticlusterV1alpha1Client for the given config and
+// panics if there is an error in the config.
+func NewForConfigOrDie(c *rest.Config) *MulticlusterV1alpha1Client {
+	client, err := NewForConfig(c)
+	if err != nil {
+		panic(err)
+	}
+	return client
+}
+
+// New creates a new MulticlusterV1alpha1Client for the given RESTClient.
+func New(c rest.Interface) *MulticlusterV1alpha1Client {
+	return &MulticlusterV1alpha1Client{c}
+}
+
+func setConfigDefaults(config *rest.Config) error {
+	gv := v1alpha1.SchemeGroupVersion
+	config.GroupVersion = &gv
+	config.APIPath = "/apis"
+	config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
+
+	if config.UserAgent == "" {
+		config.UserAgent = rest.DefaultKubernetesUserAgent()
+	}
+
+	return nil
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *MulticlusterV1alpha1Client) RESTClient() rest.Interface {
+	if c == nil {
+		return nil
+	}
+	return c.restClient
+}
diff --git a/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/doc.go b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/doc.go
new file mode 100644
index 0000000..df51baa
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// This package has the automatically generated typed clients.
+package v1alpha1
diff --git a/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/fake/doc.go b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/fake/doc.go
new file mode 100644
index 0000000..16f4439
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/fake/fake_apis_client.go b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/fake/fake_apis_client.go
new file mode 100644
index 0000000..bac20e8
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/fake/fake_apis_client.go
@@ -0,0 +1,44 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	v1alpha1 "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1"
+	rest "k8s.io/client-go/rest"
+	testing "k8s.io/client-go/testing"
+)
+
+type FakeMulticlusterV1alpha1 struct {
+	*testing.Fake
+}
+
+func (c *FakeMulticlusterV1alpha1) ServiceExports(namespace string) v1alpha1.ServiceExportInterface {
+	return &FakeServiceExports{c, namespace}
+}
+
+func (c *FakeMulticlusterV1alpha1) ServiceImports(namespace string) v1alpha1.ServiceImportInterface {
+	return &FakeServiceImports{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeMulticlusterV1alpha1) RESTClient() rest.Interface {
+	var ret *rest.RESTClient
+	return ret
+}
diff --git a/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/fake/fake_serviceexport.go b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/fake/fake_serviceexport.go
new file mode 100644
index 0000000..a1b4f76
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/fake/fake_serviceexport.go
@@ -0,0 +1,140 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	testing "k8s.io/client-go/testing"
+	v1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
+)
+
+// FakeServiceExports implements ServiceExportInterface
+type FakeServiceExports struct {
+	Fake *FakeMulticlusterV1alpha1
+	ns   string
+}
+
+var serviceexportsResource = schema.GroupVersionResource{Group: "multicluster.x-k8s.io", Version: "v1alpha1", Resource: "serviceexports"}
+
+var serviceexportsKind = schema.GroupVersionKind{Group: "multicluster.x-k8s.io", Version: "v1alpha1", Kind: "ServiceExport"}
+
+// Get takes name of the serviceExport, and returns the corresponding serviceExport object, and an error if there is any.
+func (c *FakeServiceExports) Get(name string, options v1.GetOptions) (result *v1alpha1.ServiceExport, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewGetAction(serviceexportsResource, c.ns, name), &v1alpha1.ServiceExport{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.ServiceExport), err
+}
+
+// List takes label and field selectors, and returns the list of ServiceExports that match those selectors.
+func (c *FakeServiceExports) List(opts v1.ListOptions) (result *v1alpha1.ServiceExportList, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewListAction(serviceexportsResource, serviceexportsKind, c.ns, opts), &v1alpha1.ServiceExportList{})
+
+	if obj == nil {
+		return nil, err
+	}
+
+	label, _, _ := testing.ExtractFromListOptions(opts)
+	if label == nil {
+		label = labels.Everything()
+	}
+	list := &v1alpha1.ServiceExportList{ListMeta: obj.(*v1alpha1.ServiceExportList).ListMeta}
+	for _, item := range obj.(*v1alpha1.ServiceExportList).Items {
+		if label.Matches(labels.Set(item.Labels)) {
+			list.Items = append(list.Items, item)
+		}
+	}
+	return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested serviceExports.
+func (c *FakeServiceExports) Watch(opts v1.ListOptions) (watch.Interface, error) {
+	return c.Fake.
+		InvokesWatch(testing.NewWatchAction(serviceexportsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a serviceExport and creates it.  Returns the server's representation of the serviceExport, and an error, if there is any.
+func (c *FakeServiceExports) Create(serviceExport *v1alpha1.ServiceExport) (result *v1alpha1.ServiceExport, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewCreateAction(serviceexportsResource, c.ns, serviceExport), &v1alpha1.ServiceExport{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.ServiceExport), err
+}
+
+// Update takes the representation of a serviceExport and updates it. Returns the server's representation of the serviceExport, and an error, if there is any.
+func (c *FakeServiceExports) Update(serviceExport *v1alpha1.ServiceExport) (result *v1alpha1.ServiceExport, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateAction(serviceexportsResource, c.ns, serviceExport), &v1alpha1.ServiceExport{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.ServiceExport), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeServiceExports) UpdateStatus(serviceExport *v1alpha1.ServiceExport) (*v1alpha1.ServiceExport, error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateSubresourceAction(serviceexportsResource, "status", c.ns, serviceExport), &v1alpha1.ServiceExport{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.ServiceExport), err
+}
+
+// Delete takes name of the serviceExport and deletes it. Returns an error if one occurs.
+func (c *FakeServiceExports) Delete(name string, options *v1.DeleteOptions) error {
+	_, err := c.Fake.
+		Invokes(testing.NewDeleteAction(serviceexportsResource, c.ns, name), &v1alpha1.ServiceExport{})
+
+	return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeServiceExports) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+	action := testing.NewDeleteCollectionAction(serviceexportsResource, c.ns, listOptions)
+
+	_, err := c.Fake.Invokes(action, &v1alpha1.ServiceExportList{})
+	return err
+}
+
+// Patch applies the patch and returns the patched serviceExport.
+func (c *FakeServiceExports) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ServiceExport, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewPatchSubresourceAction(serviceexportsResource, c.ns, name, pt, data, subresources...), &v1alpha1.ServiceExport{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.ServiceExport), err
+}
diff --git a/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/fake/fake_serviceimport.go b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/fake/fake_serviceimport.go
new file mode 100644
index 0000000..56ad424
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/fake/fake_serviceimport.go
@@ -0,0 +1,140 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	testing "k8s.io/client-go/testing"
+	v1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
+)
+
+// FakeServiceImports implements ServiceImportInterface
+type FakeServiceImports struct {
+	Fake *FakeMulticlusterV1alpha1
+	ns   string
+}
+
+var serviceimportsResource = schema.GroupVersionResource{Group: "multicluster.x-k8s.io", Version: "v1alpha1", Resource: "serviceimports"}
+
+var serviceimportsKind = schema.GroupVersionKind{Group: "multicluster.x-k8s.io", Version: "v1alpha1", Kind: "ServiceImport"}
+
+// Get takes name of the serviceImport, and returns the corresponding serviceImport object, and an error if there is any.
+func (c *FakeServiceImports) Get(name string, options v1.GetOptions) (result *v1alpha1.ServiceImport, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewGetAction(serviceimportsResource, c.ns, name), &v1alpha1.ServiceImport{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.ServiceImport), err
+}
+
+// List takes label and field selectors, and returns the list of ServiceImports that match those selectors.
+func (c *FakeServiceImports) List(opts v1.ListOptions) (result *v1alpha1.ServiceImportList, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewListAction(serviceimportsResource, serviceimportsKind, c.ns, opts), &v1alpha1.ServiceImportList{})
+
+	if obj == nil {
+		return nil, err
+	}
+
+	label, _, _ := testing.ExtractFromListOptions(opts)
+	if label == nil {
+		label = labels.Everything()
+	}
+	list := &v1alpha1.ServiceImportList{ListMeta: obj.(*v1alpha1.ServiceImportList).ListMeta}
+	for _, item := range obj.(*v1alpha1.ServiceImportList).Items {
+		if label.Matches(labels.Set(item.Labels)) {
+			list.Items = append(list.Items, item)
+		}
+	}
+	return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested serviceImports.
+func (c *FakeServiceImports) Watch(opts v1.ListOptions) (watch.Interface, error) {
+	return c.Fake.
+		InvokesWatch(testing.NewWatchAction(serviceimportsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a serviceImport and creates it.  Returns the server's representation of the serviceImport, and an error, if there is any.
+func (c *FakeServiceImports) Create(serviceImport *v1alpha1.ServiceImport) (result *v1alpha1.ServiceImport, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewCreateAction(serviceimportsResource, c.ns, serviceImport), &v1alpha1.ServiceImport{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.ServiceImport), err
+}
+
+// Update takes the representation of a serviceImport and updates it. Returns the server's representation of the serviceImport, and an error, if there is any.
+func (c *FakeServiceImports) Update(serviceImport *v1alpha1.ServiceImport) (result *v1alpha1.ServiceImport, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateAction(serviceimportsResource, c.ns, serviceImport), &v1alpha1.ServiceImport{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.ServiceImport), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeServiceImports) UpdateStatus(serviceImport *v1alpha1.ServiceImport) (*v1alpha1.ServiceImport, error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateSubresourceAction(serviceimportsResource, "status", c.ns, serviceImport), &v1alpha1.ServiceImport{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.ServiceImport), err
+}
+
+// Delete takes name of the serviceImport and deletes it. Returns an error if one occurs.
+func (c *FakeServiceImports) Delete(name string, options *v1.DeleteOptions) error {
+	_, err := c.Fake.
+		Invokes(testing.NewDeleteAction(serviceimportsResource, c.ns, name), &v1alpha1.ServiceImport{})
+
+	return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeServiceImports) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+	action := testing.NewDeleteCollectionAction(serviceimportsResource, c.ns, listOptions)
+
+	_, err := c.Fake.Invokes(action, &v1alpha1.ServiceImportList{})
+	return err
+}
+
+// Patch applies the patch and returns the patched serviceImport.
+func (c *FakeServiceImports) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ServiceImport, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewPatchSubresourceAction(serviceimportsResource, c.ns, name, pt, data, subresources...), &v1alpha1.ServiceImport{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.ServiceImport), err
+}
diff --git a/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/generated_expansion.go b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/generated_expansion.go
new file mode 100644
index 0000000..4586945
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/generated_expansion.go
@@ -0,0 +1,23 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1alpha1
+
+type ServiceExportExpansion interface{}
+
+type ServiceImportExpansion interface{}
diff --git a/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/serviceexport.go b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/serviceexport.go
new file mode 100644
index 0000000..3ff6b1d
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/serviceexport.go
@@ -0,0 +1,191 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	"time"
+
+	scheme "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned/scheme"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	rest "k8s.io/client-go/rest"
+	v1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
+)
+
+// ServiceExportsGetter has a method to return a ServiceExportInterface.
+// A group's client should implement this interface.
+type ServiceExportsGetter interface {
+	ServiceExports(namespace string) ServiceExportInterface
+}
+
+// ServiceExportInterface has methods to work with ServiceExport resources.
+type ServiceExportInterface interface {
+	Create(*v1alpha1.ServiceExport) (*v1alpha1.ServiceExport, error)
+	Update(*v1alpha1.ServiceExport) (*v1alpha1.ServiceExport, error)
+	UpdateStatus(*v1alpha1.ServiceExport) (*v1alpha1.ServiceExport, error)
+	Delete(name string, options *v1.DeleteOptions) error
+	DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
+	Get(name string, options v1.GetOptions) (*v1alpha1.ServiceExport, error)
+	List(opts v1.ListOptions) (*v1alpha1.ServiceExportList, error)
+	Watch(opts v1.ListOptions) (watch.Interface, error)
+	Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ServiceExport, err error)
+	ServiceExportExpansion
+}
+
+// serviceExports implements ServiceExportInterface
+type serviceExports struct {
+	client rest.Interface
+	ns     string
+}
+
+// newServiceExports returns a ServiceExports
+func newServiceExports(c *MulticlusterV1alpha1Client, namespace string) *serviceExports {
+	return &serviceExports{
+		client: c.RESTClient(),
+		ns:     namespace,
+	}
+}
+
+// Get takes name of the serviceExport, and returns the corresponding serviceExport object, and an error if there is any.
+func (c *serviceExports) Get(name string, options v1.GetOptions) (result *v1alpha1.ServiceExport, err error) {
+	result = &v1alpha1.ServiceExport{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("serviceexports").
+		Name(name).
+		VersionedParams(&options, scheme.ParameterCodec).
+		Do().
+		Into(result)
+	return
+}
+
+// List takes label and field selectors, and returns the list of ServiceExports that match those selectors.
+func (c *serviceExports) List(opts v1.ListOptions) (result *v1alpha1.ServiceExportList, err error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	result = &v1alpha1.ServiceExportList{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("serviceexports").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Do().
+		Into(result)
+	return
+}
+
+// Watch returns a watch.Interface that watches the requested serviceExports.
+func (c *serviceExports) Watch(opts v1.ListOptions) (watch.Interface, error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	opts.Watch = true
+	return c.client.Get().
+		Namespace(c.ns).
+		Resource("serviceexports").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Watch()
+}
+
+// Create takes the representation of a serviceExport and creates it.  Returns the server's representation of the serviceExport, and an error, if there is any.
+func (c *serviceExports) Create(serviceExport *v1alpha1.ServiceExport) (result *v1alpha1.ServiceExport, err error) {
+	result = &v1alpha1.ServiceExport{}
+	err = c.client.Post().
+		Namespace(c.ns).
+		Resource("serviceexports").
+		Body(serviceExport).
+		Do().
+		Into(result)
+	return
+}
+
+// Update takes the representation of a serviceExport and updates it. Returns the server's representation of the serviceExport, and an error, if there is any.
+func (c *serviceExports) Update(serviceExport *v1alpha1.ServiceExport) (result *v1alpha1.ServiceExport, err error) {
+	result = &v1alpha1.ServiceExport{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("serviceexports").
+		Name(serviceExport.Name).
+		Body(serviceExport).
+		Do().
+		Into(result)
+	return
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+
+func (c *serviceExports) UpdateStatus(serviceExport *v1alpha1.ServiceExport) (result *v1alpha1.ServiceExport, err error) {
+	result = &v1alpha1.ServiceExport{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("serviceexports").
+		Name(serviceExport.Name).
+		SubResource("status").
+		Body(serviceExport).
+		Do().
+		Into(result)
+	return
+}
+
+// Delete takes name of the serviceExport and deletes it. Returns an error if one occurs.
+func (c *serviceExports) Delete(name string, options *v1.DeleteOptions) error {
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("serviceexports").
+		Name(name).
+		Body(options).
+		Do().
+		Error()
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *serviceExports) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+	var timeout time.Duration
+	if listOptions.TimeoutSeconds != nil {
+		timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
+	}
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("serviceexports").
+		VersionedParams(&listOptions, scheme.ParameterCodec).
+		Timeout(timeout).
+		Body(options).
+		Do().
+		Error()
+}
+
+// Patch applies the patch and returns the patched serviceExport.
+func (c *serviceExports) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ServiceExport, err error) {
+	result = &v1alpha1.ServiceExport{}
+	err = c.client.Patch(pt).
+		Namespace(c.ns).
+		Resource("serviceexports").
+		SubResource(subresources...).
+		Name(name).
+		Body(data).
+		Do().
+		Into(result)
+	return
+}
diff --git a/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/serviceimport.go b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/serviceimport.go
new file mode 100644
index 0000000..df785c3
--- /dev/null
+++ b/pkg/mcs/client/clientset/versioned/typed/apis/v1alpha1/serviceimport.go
@@ -0,0 +1,191 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	"time"
+
+	scheme "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned/scheme"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	rest "k8s.io/client-go/rest"
+	v1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
+)
+
+// ServiceImportsGetter has a method to return a ServiceImportInterface.
+// A group's client should implement this interface.
+type ServiceImportsGetter interface {
+	ServiceImports(namespace string) ServiceImportInterface
+}
+
+// ServiceImportInterface has methods to work with ServiceImport resources.
+type ServiceImportInterface interface {
+	Create(*v1alpha1.ServiceImport) (*v1alpha1.ServiceImport, error)
+	Update(*v1alpha1.ServiceImport) (*v1alpha1.ServiceImport, error)
+	UpdateStatus(*v1alpha1.ServiceImport) (*v1alpha1.ServiceImport, error)
+	Delete(name string, options *v1.DeleteOptions) error
+	DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
+	Get(name string, options v1.GetOptions) (*v1alpha1.ServiceImport, error)
+	List(opts v1.ListOptions) (*v1alpha1.ServiceImportList, error)
+	Watch(opts v1.ListOptions) (watch.Interface, error)
+	Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ServiceImport, err error)
+	ServiceImportExpansion
+}
+
+// serviceImports implements ServiceImportInterface
+type serviceImports struct {
+	client rest.Interface
+	ns     string
+}
+
+// newServiceImports returns a ServiceImports
+func newServiceImports(c *MulticlusterV1alpha1Client, namespace string) *serviceImports {
+	return &serviceImports{
+		client: c.RESTClient(),
+		ns:     namespace,
+	}
+}
+
+// Get takes name of the serviceImport, and returns the corresponding serviceImport object, and an error if there is any.
+func (c *serviceImports) Get(name string, options v1.GetOptions) (result *v1alpha1.ServiceImport, err error) {
+	result = &v1alpha1.ServiceImport{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("serviceimports").
+		Name(name).
+		VersionedParams(&options, scheme.ParameterCodec).
+		Do().
+		Into(result)
+	return
+}
+
+// List takes label and field selectors, and returns the list of ServiceImports that match those selectors.
+func (c *serviceImports) List(opts v1.ListOptions) (result *v1alpha1.ServiceImportList, err error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	result = &v1alpha1.ServiceImportList{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("serviceimports").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Do().
+		Into(result)
+	return
+}
+
+// Watch returns a watch.Interface that watches the requested serviceImports.
+func (c *serviceImports) Watch(opts v1.ListOptions) (watch.Interface, error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	opts.Watch = true
+	return c.client.Get().
+		Namespace(c.ns).
+		Resource("serviceimports").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Watch()
+}
+
+// Create takes the representation of a serviceImport and creates it.  Returns the server's representation of the serviceImport, and an error, if there is any.
+func (c *serviceImports) Create(serviceImport *v1alpha1.ServiceImport) (result *v1alpha1.ServiceImport, err error) {
+	result = &v1alpha1.ServiceImport{}
+	err = c.client.Post().
+		Namespace(c.ns).
+		Resource("serviceimports").
+		Body(serviceImport).
+		Do().
+		Into(result)
+	return
+}
+
+// Update takes the representation of a serviceImport and updates it. Returns the server's representation of the serviceImport, and an error, if there is any.
+func (c *serviceImports) Update(serviceImport *v1alpha1.ServiceImport) (result *v1alpha1.ServiceImport, err error) {
+	result = &v1alpha1.ServiceImport{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("serviceimports").
+		Name(serviceImport.Name).
+		Body(serviceImport).
+		Do().
+		Into(result)
+	return
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+
+func (c *serviceImports) UpdateStatus(serviceImport *v1alpha1.ServiceImport) (result *v1alpha1.ServiceImport, err error) {
+	result = &v1alpha1.ServiceImport{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("serviceimports").
+		Name(serviceImport.Name).
+		SubResource("status").
+		Body(serviceImport).
+		Do().
+		Into(result)
+	return
+}
+
+// Delete takes name of the serviceImport and deletes it. Returns an error if one occurs.
+func (c *serviceImports) Delete(name string, options *v1.DeleteOptions) error {
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("serviceimports").
+		Name(name).
+		Body(options).
+		Do().
+		Error()
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *serviceImports) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+	var timeout time.Duration
+	if listOptions.TimeoutSeconds != nil {
+		timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
+	}
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("serviceimports").
+		VersionedParams(&listOptions, scheme.ParameterCodec).
+		Timeout(timeout).
+		Body(options).
+		Do().
+		Error()
+}
+
+// Patch applies the patch and returns the patched serviceImport.
+func (c *serviceImports) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ServiceImport, err error) {
+	result = &v1alpha1.ServiceImport{}
+	err = c.client.Patch(pt).
+		Namespace(c.ns).
+		Resource("serviceimports").
+		SubResource(subresources...).
+		Name(name).
+		Body(data).
+		Do().
+		Into(result)
+	return
+}
diff --git a/pkg/mcs/client/informers/externalversions/apis/interface.go b/pkg/mcs/client/informers/externalversions/apis/interface.go
new file mode 100644
index 0000000..de2d396
--- /dev/null
+++ b/pkg/mcs/client/informers/externalversions/apis/interface.go
@@ -0,0 +1,46 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package apis
+
+import (
+	v1alpha1 "github.com/submariner-io/lighthouse/pkg/mcs/client/informers/externalversions/apis/v1alpha1"
+	internalinterfaces "github.com/submariner-io/lighthouse/pkg/mcs/client/informers/externalversions/internalinterfaces"
+)
+
+// Interface provides access to each of this group's versions.
+type Interface interface {
+	// V1alpha1 provides access to shared informers for resources in V1alpha1.
+	V1alpha1() v1alpha1.Interface
+}
+
+type group struct {
+	factory          internalinterfaces.SharedInformerFactory
+	namespace        string
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+}
+
+// New returns a new Interface.
+func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
+	return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
+}
+
+// V1alpha1 returns a new v1alpha1.Interface.
+func (g *group) V1alpha1() v1alpha1.Interface {
+	return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions)
+}
diff --git a/pkg/mcs/client/informers/externalversions/apis/v1alpha1/interface.go b/pkg/mcs/client/informers/externalversions/apis/v1alpha1/interface.go
new file mode 100644
index 0000000..34feb04
--- /dev/null
+++ b/pkg/mcs/client/informers/externalversions/apis/v1alpha1/interface.go
@@ -0,0 +1,52 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	internalinterfaces "github.com/submariner-io/lighthouse/pkg/mcs/client/informers/externalversions/internalinterfaces"
+)
+
+// Interface provides access to all the informers in this group version.
+type Interface interface {
+	// ServiceExports returns a ServiceExportInformer.
+	ServiceExports() ServiceExportInformer
+	// ServiceImports returns a ServiceImportInformer.
+	ServiceImports() ServiceImportInformer
+}
+
+type version struct {
+	factory          internalinterfaces.SharedInformerFactory
+	namespace        string
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+}
+
+// New returns a new Interface.
+func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
+	return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
+}
+
+// ServiceExports returns a ServiceExportInformer.
+func (v *version) ServiceExports() ServiceExportInformer {
+	return &serviceExportInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
+}
+
+// ServiceImports returns a ServiceImportInformer.
+func (v *version) ServiceImports() ServiceImportInformer {
+	return &serviceImportInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
+}
diff --git a/pkg/mcs/client/informers/externalversions/apis/v1alpha1/serviceexport.go b/pkg/mcs/client/informers/externalversions/apis/v1alpha1/serviceexport.go
new file mode 100644
index 0000000..ce889f3
--- /dev/null
+++ b/pkg/mcs/client/informers/externalversions/apis/v1alpha1/serviceexport.go
@@ -0,0 +1,89 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	time "time"
+
+	versioned "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned"
+	internalinterfaces "github.com/submariner-io/lighthouse/pkg/mcs/client/informers/externalversions/internalinterfaces"
+	v1alpha1 "github.com/submariner-io/lighthouse/pkg/mcs/client/listers/apis/v1alpha1"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	watch "k8s.io/apimachinery/pkg/watch"
+	cache "k8s.io/client-go/tools/cache"
+	apisv1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
+)
+
+// ServiceExportInformer provides access to a shared informer and lister for
+// ServiceExports.
+type ServiceExportInformer interface {
+	Informer() cache.SharedIndexInformer
+	Lister() v1alpha1.ServiceExportLister
+}
+
+type serviceExportInformer struct {
+	factory          internalinterfaces.SharedInformerFactory
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+	namespace        string
+}
+
+// NewServiceExportInformer constructs a new informer for ServiceExport type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewServiceExportInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
+	return NewFilteredServiceExportInformer(client, namespace, resyncPeriod, indexers, nil)
+}
+
+// NewFilteredServiceExportInformer constructs a new informer for ServiceExport type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewFilteredServiceExportInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
+	return cache.NewSharedIndexInformer(
+		&cache.ListWatch{
+			ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.MulticlusterV1alpha1().ServiceExports(namespace).List(options)
+			},
+			WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.MulticlusterV1alpha1().ServiceExports(namespace).Watch(options)
+			},
+		},
+		&apisv1alpha1.ServiceExport{},
+		resyncPeriod,
+		indexers,
+	)
+}
+
+func (f *serviceExportInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
+	return NewFilteredServiceExportInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
+}
+
+func (f *serviceExportInformer) Informer() cache.SharedIndexInformer {
+	return f.factory.InformerFor(&apisv1alpha1.ServiceExport{}, f.defaultInformer)
+}
+
+func (f *serviceExportInformer) Lister() v1alpha1.ServiceExportLister {
+	return v1alpha1.NewServiceExportLister(f.Informer().GetIndexer())
+}
diff --git a/pkg/mcs/client/informers/externalversions/apis/v1alpha1/serviceimport.go b/pkg/mcs/client/informers/externalversions/apis/v1alpha1/serviceimport.go
new file mode 100644
index 0000000..12e61b8
--- /dev/null
+++ b/pkg/mcs/client/informers/externalversions/apis/v1alpha1/serviceimport.go
@@ -0,0 +1,89 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	time "time"
+
+	versioned "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned"
+	internalinterfaces "github.com/submariner-io/lighthouse/pkg/mcs/client/informers/externalversions/internalinterfaces"
+	v1alpha1 "github.com/submariner-io/lighthouse/pkg/mcs/client/listers/apis/v1alpha1"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	watch "k8s.io/apimachinery/pkg/watch"
+	cache "k8s.io/client-go/tools/cache"
+	apisv1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
+)
+
+// ServiceImportInformer provides access to a shared informer and lister for
+// ServiceImports.
+type ServiceImportInformer interface {
+	Informer() cache.SharedIndexInformer
+	Lister() v1alpha1.ServiceImportLister
+}
+
+type serviceImportInformer struct {
+	factory          internalinterfaces.SharedInformerFactory
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+	namespace        string
+}
+
+// NewServiceImportInformer constructs a new informer for ServiceImport type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewServiceImportInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
+	return NewFilteredServiceImportInformer(client, namespace, resyncPeriod, indexers, nil)
+}
+
+// NewFilteredServiceImportInformer constructs a new informer for ServiceImport type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewFilteredServiceImportInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
+	return cache.NewSharedIndexInformer(
+		&cache.ListWatch{
+			ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.MulticlusterV1alpha1().ServiceImports(namespace).List(options)
+			},
+			WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.MulticlusterV1alpha1().ServiceImports(namespace).Watch(options)
+			},
+		},
+		&apisv1alpha1.ServiceImport{},
+		resyncPeriod,
+		indexers,
+	)
+}
+
+func (f *serviceImportInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
+	return NewFilteredServiceImportInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
+}
+
+func (f *serviceImportInformer) Informer() cache.SharedIndexInformer {
+	return f.factory.InformerFor(&apisv1alpha1.ServiceImport{}, f.defaultInformer)
+}
+
+func (f *serviceImportInformer) Lister() v1alpha1.ServiceImportLister {
+	return v1alpha1.NewServiceImportLister(f.Informer().GetIndexer())
+}
diff --git a/pkg/mcs/client/informers/externalversions/factory.go b/pkg/mcs/client/informers/externalversions/factory.go
new file mode 100644
index 0000000..02664f5
--- /dev/null
+++ b/pkg/mcs/client/informers/externalversions/factory.go
@@ -0,0 +1,180 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package externalversions
+
+import (
+	reflect "reflect"
+	sync "sync"
+	time "time"
+
+	versioned "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned"
+	apis "github.com/submariner-io/lighthouse/pkg/mcs/client/informers/externalversions/apis"
+	internalinterfaces "github.com/submariner-io/lighthouse/pkg/mcs/client/informers/externalversions/internalinterfaces"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	cache "k8s.io/client-go/tools/cache"
+)
+
+// SharedInformerOption defines the functional option type for SharedInformerFactory.
+type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory
+
+type sharedInformerFactory struct {
+	client           versioned.Interface
+	namespace        string
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+	lock             sync.Mutex
+	defaultResync    time.Duration
+	customResync     map[reflect.Type]time.Duration
+
+	informers map[reflect.Type]cache.SharedIndexInformer
+	// startedInformers is used for tracking which informers have been started.
+	// This allows Start() to be called multiple times safely.
+	startedInformers map[reflect.Type]bool
+}
+
+// WithCustomResyncConfig sets a custom resync period for the specified informer types.
+func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption {
+	return func(factory *sharedInformerFactory) *sharedInformerFactory {
+		for k, v := range resyncConfig {
+			factory.customResync[reflect.TypeOf(k)] = v
+		}
+		return factory
+	}
+}
+
+// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.
+func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {
+	return func(factory *sharedInformerFactory) *sharedInformerFactory {
+		factory.tweakListOptions = tweakListOptions
+		return factory
+	}
+}
+
+// WithNamespace limits the SharedInformerFactory to the specified namespace.
+func WithNamespace(namespace string) SharedInformerOption {
+	return func(factory *sharedInformerFactory) *sharedInformerFactory {
+		factory.namespace = namespace
+		return factory
+	}
+}
+
+// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.
+func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory {
+	return NewSharedInformerFactoryWithOptions(client, defaultResync)
+}
+
+// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
+// Listers obtained via this SharedInformerFactory will be subject to the same filters
+// as specified here.
+// Deprecated: Please use NewSharedInformerFactoryWithOptions instead
+func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {
+	return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))
+}
+
+// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.
+func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory {
+	factory := &sharedInformerFactory{
+		client:           client,
+		namespace:        v1.NamespaceAll,
+		defaultResync:    defaultResync,
+		informers:        make(map[reflect.Type]cache.SharedIndexInformer),
+		startedInformers: make(map[reflect.Type]bool),
+		customResync:     make(map[reflect.Type]time.Duration),
+	}
+
+	// Apply all options
+	for _, opt := range options {
+		factory = opt(factory)
+	}
+
+	return factory
+}
+
+// Start initializes all requested informers.
+func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
+	f.lock.Lock()
+	defer f.lock.Unlock()
+
+	for informerType, informer := range f.informers {
+		if !f.startedInformers[informerType] {
+			go informer.Run(stopCh)
+			f.startedInformers[informerType] = true
+		}
+	}
+}
+
+// WaitForCacheSync waits for all started informers' cache were synced.
+func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
+	informers := func() map[reflect.Type]cache.SharedIndexInformer {
+		f.lock.Lock()
+		defer f.lock.Unlock()
+
+		informers := map[reflect.Type]cache.SharedIndexInformer{}
+		for informerType, informer := range f.informers {
+			if f.startedInformers[informerType] {
+				informers[informerType] = informer
+			}
+		}
+		return informers
+	}()
+
+	res := map[reflect.Type]bool{}
+	for informType, informer := range informers {
+		res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
+	}
+	return res
+}
+
+// InternalInformerFor returns the SharedIndexInformer for obj using an internal
+// client.
+func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {
+	f.lock.Lock()
+	defer f.lock.Unlock()
+
+	informerType := reflect.TypeOf(obj)
+	informer, exists := f.informers[informerType]
+	if exists {
+		return informer
+	}
+
+	resyncPeriod, exists := f.customResync[informerType]
+	if !exists {
+		resyncPeriod = f.defaultResync
+	}
+
+	informer = newFunc(f.client, resyncPeriod)
+	f.informers[informerType] = informer
+
+	return informer
+}
+
+// SharedInformerFactory provides shared informers for resources in all known
+// API group versions.
+type SharedInformerFactory interface {
+	internalinterfaces.SharedInformerFactory
+	ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
+	WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
+
+	Multicluster() apis.Interface
+}
+
+func (f *sharedInformerFactory) Multicluster() apis.Interface {
+	return apis.New(f, f.namespace, f.tweakListOptions)
+}
diff --git a/pkg/mcs/client/informers/externalversions/generic.go b/pkg/mcs/client/informers/externalversions/generic.go
new file mode 100644
index 0000000..a19cd51
--- /dev/null
+++ b/pkg/mcs/client/informers/externalversions/generic.go
@@ -0,0 +1,64 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package externalversions
+
+import (
+	"fmt"
+
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	cache "k8s.io/client-go/tools/cache"
+	v1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
+)
+
+// GenericInformer is type of SharedIndexInformer which will locate and delegate to other
+// sharedInformers based on type
+type GenericInformer interface {
+	Informer() cache.SharedIndexInformer
+	Lister() cache.GenericLister
+}
+
+type genericInformer struct {
+	informer cache.SharedIndexInformer
+	resource schema.GroupResource
+}
+
+// Informer returns the SharedIndexInformer.
+func (f *genericInformer) Informer() cache.SharedIndexInformer {
+	return f.informer
+}
+
+// Lister returns the GenericLister.
+func (f *genericInformer) Lister() cache.GenericLister {
+	return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)
+}
+
+// ForResource gives generic access to a shared informer of the matching type
+// TODO extend this to unknown resources with a client pool
+func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
+	switch resource {
+	// Group=multicluster.x-k8s.io, Version=v1alpha1
+	case v1alpha1.SchemeGroupVersion.WithResource("serviceexports"):
+		return &genericInformer{resource: resource.GroupResource(), informer: f.Multicluster().V1alpha1().ServiceExports().Informer()}, nil
+	case v1alpha1.SchemeGroupVersion.WithResource("serviceimports"):
+		return &genericInformer{resource: resource.GroupResource(), informer: f.Multicluster().V1alpha1().ServiceImports().Informer()}, nil
+
+	}
+
+	return nil, fmt.Errorf("no informer found for %v", resource)
+}
diff --git a/pkg/mcs/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/mcs/client/informers/externalversions/internalinterfaces/factory_interfaces.go
new file mode 100644
index 0000000..62505d2
--- /dev/null
+++ b/pkg/mcs/client/informers/externalversions/internalinterfaces/factory_interfaces.go
@@ -0,0 +1,40 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package internalinterfaces
+
+import (
+	time "time"
+
+	versioned "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	cache "k8s.io/client-go/tools/cache"
+)
+
+// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer.
+type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer
+
+// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
+type SharedInformerFactory interface {
+	Start(stopCh <-chan struct{})
+	InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
+}
+
+// TweakListOptionsFunc is a function that transforms a v1.ListOptions.
+type TweakListOptionsFunc func(*v1.ListOptions)
diff --git a/pkg/mcs/client/listers/apis/v1alpha1/expansion_generated.go b/pkg/mcs/client/listers/apis/v1alpha1/expansion_generated.go
new file mode 100644
index 0000000..36828ce
--- /dev/null
+++ b/pkg/mcs/client/listers/apis/v1alpha1/expansion_generated.go
@@ -0,0 +1,35 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v1alpha1
+
+// ServiceExportListerExpansion allows custom methods to be added to
+// ServiceExportLister.
+type ServiceExportListerExpansion interface{}
+
+// ServiceExportNamespaceListerExpansion allows custom methods to be added to
+// ServiceExportNamespaceLister.
+type ServiceExportNamespaceListerExpansion interface{}
+
+// ServiceImportListerExpansion allows custom methods to be added to
+// ServiceImportLister.
+type ServiceImportListerExpansion interface{}
+
+// ServiceImportNamespaceListerExpansion allows custom methods to be added to
+// ServiceImportNamespaceLister.
+type ServiceImportNamespaceListerExpansion interface{}
diff --git a/pkg/mcs/client/listers/apis/v1alpha1/serviceexport.go b/pkg/mcs/client/listers/apis/v1alpha1/serviceexport.go
new file mode 100644
index 0000000..d60c474
--- /dev/null
+++ b/pkg/mcs/client/listers/apis/v1alpha1/serviceexport.go
@@ -0,0 +1,94 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	"k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/client-go/tools/cache"
+	v1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
+)
+
+// ServiceExportLister helps list ServiceExports.
+type ServiceExportLister interface {
+	// List lists all ServiceExports in the indexer.
+	List(selector labels.Selector) (ret []*v1alpha1.ServiceExport, err error)
+	// ServiceExports returns an object that can list and get ServiceExports.
+	ServiceExports(namespace string) ServiceExportNamespaceLister
+	ServiceExportListerExpansion
+}
+
+// serviceExportLister implements the ServiceExportLister interface.
+type serviceExportLister struct {
+	indexer cache.Indexer
+}
+
+// NewServiceExportLister returns a new ServiceExportLister.
+func NewServiceExportLister(indexer cache.Indexer) ServiceExportLister {
+	return &serviceExportLister{indexer: indexer}
+}
+
+// List lists all ServiceExports in the indexer.
+func (s *serviceExportLister) List(selector labels.Selector) (ret []*v1alpha1.ServiceExport, err error) {
+	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
+		ret = append(ret, m.(*v1alpha1.ServiceExport))
+	})
+	return ret, err
+}
+
+// ServiceExports returns an object that can list and get ServiceExports.
+func (s *serviceExportLister) ServiceExports(namespace string) ServiceExportNamespaceLister {
+	return serviceExportNamespaceLister{indexer: s.indexer, namespace: namespace}
+}
+
+// ServiceExportNamespaceLister helps list and get ServiceExports.
+type ServiceExportNamespaceLister interface {
+	// List lists all ServiceExports in the indexer for a given namespace.
+	List(selector labels.Selector) (ret []*v1alpha1.ServiceExport, err error)
+	// Get retrieves the ServiceExport from the indexer for a given namespace and name.
+	Get(name string) (*v1alpha1.ServiceExport, error)
+	ServiceExportNamespaceListerExpansion
+}
+
+// serviceExportNamespaceLister implements the ServiceExportNamespaceLister
+// interface.
+type serviceExportNamespaceLister struct {
+	indexer   cache.Indexer
+	namespace string
+}
+
+// List lists all ServiceExports in the indexer for a given namespace.
+func (s serviceExportNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ServiceExport, err error) {
+	err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
+		ret = append(ret, m.(*v1alpha1.ServiceExport))
+	})
+	return ret, err
+}
+
+// Get retrieves the ServiceExport from the indexer for a given namespace and name.
+func (s serviceExportNamespaceLister) Get(name string) (*v1alpha1.ServiceExport, error) {
+	obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
+	if err != nil {
+		return nil, err
+	}
+	if !exists {
+		return nil, errors.NewNotFound(v1alpha1.Resource("serviceexport"), name)
+	}
+	return obj.(*v1alpha1.ServiceExport), nil
+}
diff --git a/pkg/mcs/client/listers/apis/v1alpha1/serviceimport.go b/pkg/mcs/client/listers/apis/v1alpha1/serviceimport.go
new file mode 100644
index 0000000..51b555a
--- /dev/null
+++ b/pkg/mcs/client/listers/apis/v1alpha1/serviceimport.go
@@ -0,0 +1,94 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	"k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/client-go/tools/cache"
+	v1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
+)
+
+// ServiceImportLister helps list ServiceImports.
+type ServiceImportLister interface {
+	// List lists all ServiceImports in the indexer.
+	List(selector labels.Selector) (ret []*v1alpha1.ServiceImport, err error)
+	// ServiceImports returns an object that can list and get ServiceImports.
+	ServiceImports(namespace string) ServiceImportNamespaceLister
+	ServiceImportListerExpansion
+}
+
+// serviceImportLister implements the ServiceImportLister interface.
+type serviceImportLister struct {
+	indexer cache.Indexer
+}
+
+// NewServiceImportLister returns a new ServiceImportLister.
+func NewServiceImportLister(indexer cache.Indexer) ServiceImportLister {
+	return &serviceImportLister{indexer: indexer}
+}
+
+// List lists all ServiceImports in the indexer.
+func (s *serviceImportLister) List(selector labels.Selector) (ret []*v1alpha1.ServiceImport, err error) {
+	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
+		ret = append(ret, m.(*v1alpha1.ServiceImport))
+	})
+	return ret, err
+}
+
+// ServiceImports returns an object that can list and get ServiceImports.
+func (s *serviceImportLister) ServiceImports(namespace string) ServiceImportNamespaceLister {
+	return serviceImportNamespaceLister{indexer: s.indexer, namespace: namespace}
+}
+
+// ServiceImportNamespaceLister helps list and get ServiceImports.
+type ServiceImportNamespaceLister interface {
+	// List lists all ServiceImports in the indexer for a given namespace.
+	List(selector labels.Selector) (ret []*v1alpha1.ServiceImport, err error)
+	// Get retrieves the ServiceImport from the indexer for a given namespace and name.
+	Get(name string) (*v1alpha1.ServiceImport, error)
+	ServiceImportNamespaceListerExpansion
+}
+
+// serviceImportNamespaceLister implements the ServiceImportNamespaceLister
+// interface.
+type serviceImportNamespaceLister struct {
+	indexer   cache.Indexer
+	namespace string
+}
+
+// List lists all ServiceImports in the indexer for a given namespace.
+func (s serviceImportNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ServiceImport, err error) {
+	err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
+		ret = append(ret, m.(*v1alpha1.ServiceImport))
+	})
+	return ret, err
+}
+
+// Get retrieves the ServiceImport from the indexer for a given namespace and name.
+func (s serviceImportNamespaceLister) Get(name string) (*v1alpha1.ServiceImport, error) {
+	obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
+	if err != nil {
+		return nil, err
+	}
+	if !exists {
+		return nil, errors.NewNotFound(v1alpha1.Resource("serviceimport"), name)
+	}
+	return obj.(*v1alpha1.ServiceImport), nil
+}
diff --git a/pkg/serviceimport/controller.go b/pkg/serviceimport/controller.go
index 38f7317..baf4fbb 100644
--- a/pkg/serviceimport/controller.go
+++ b/pkg/serviceimport/controller.go
@@ -4,16 +4,16 @@ import (
 	"fmt"
 
 	"github.com/submariner-io/admiral/pkg/log"
-	lighthousev2a1 "github.com/submariner-io/lighthouse/pkg/apis/lighthouse.submariner.io/v2alpha1"
-	lighthouseClientset "github.com/submariner-io/lighthouse/pkg/client/clientset/versioned"
-	lighthouseInformers "github.com/submariner-io/lighthouse/pkg/client/informers/externalversions"
+	mcsClientset "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned"
+	mcsInformers "github.com/submariner-io/lighthouse/pkg/mcs/client/informers/externalversions"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/rest"
 	"k8s.io/client-go/tools/cache"
 	"k8s.io/klog"
+	mcsv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
 )
 
-type NewClientsetFunc func(kubeConfig *rest.Config) (lighthouseClientset.Interface, error)
+type NewClientsetFunc func(kubeConfig *rest.Config) (mcsClientset.Interface, error)
 
 // Indirection hook for unit tests to supply fake client sets
 var NewClientset NewClientsetFunc
@@ -39,8 +39,8 @@ func getNewClientsetFunc() NewClientsetFunc {
 		return NewClientset
 	}
 
-	return func(c *rest.Config) (lighthouseClientset.Interface, error) {
-		return lighthouseClientset.NewForConfig(c)
+	return func(c *rest.Config) (mcsClientset.Interface, error) {
+		return mcsClientset.NewForConfig(c)
 	}
 }
 
@@ -52,10 +52,10 @@ func (c *Controller) Start(kubeConfig *rest.Config) error {
 		return fmt.Errorf("Error creating client set: %v", err)
 	}
 
-	informerFactory := lighthouseInformers.NewSharedInformerFactoryWithOptions(clientSet, 0,
-		lighthouseInformers.WithNamespace(metav1.NamespaceAll))
+	informerFactory := mcsInformers.NewSharedInformerFactoryWithOptions(clientSet, 0,
+		mcsInformers.WithNamespace(metav1.NamespaceAll))
 
-	c.serviceInformer = informerFactory.Lighthouse().V2alpha1().ServiceImports().Informer()
+	c.serviceInformer = informerFactory.Multicluster().V1alpha1().ServiceImports().Informer()
 	c.serviceInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
 		AddFunc: c.serviceImportCreatedOrUpdated,
 		UpdateFunc: func(oldObj, newObj interface{}) {
@@ -82,22 +82,22 @@ func (c *Controller) Stop() {
 func (c *Controller) serviceImportCreatedOrUpdated(obj interface{}) {
 	klog.V(log.DEBUG).Infof("In serviceImportCreatedOrUpdated for: %#v, ", obj)
 
-	c.store.Put(obj.(*lighthousev2a1.ServiceImport))
+	c.store.Put(obj.(*mcsv1a1.ServiceImport))
 }
 
 func (c *Controller) serviceImportDeleted(obj interface{}) {
 	klog.V(log.DEBUG).Infof("In serviceImportDeleted for: %#v, ", obj)
 
-	var si *lighthousev2a1.ServiceImport
+	var si *mcsv1a1.ServiceImport
 	var ok bool
-	if si, ok = obj.(*lighthousev2a1.ServiceImport); !ok {
+	if si, ok = obj.(*mcsv1a1.ServiceImport); !ok {
 		tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
 		if !ok {
 			klog.Errorf("Could not convert object %#v to DeletedFinalStateUnknown", obj)
 			return
 		}
 
-		si, ok = tombstone.Obj.(*lighthousev2a1.ServiceImport)
+		si, ok = tombstone.Obj.(*mcsv1a1.ServiceImport)
 		if !ok {
 			klog.Errorf("Could not convert object tombstone %#v to Unstructured", tombstone.Obj)
 			return
diff --git a/pkg/serviceimport/map.go b/pkg/serviceimport/map.go
index a260aeb..7f92e56 100644
--- a/pkg/serviceimport/map.go
+++ b/pkg/serviceimport/map.go
@@ -4,8 +4,8 @@ import (
 	"sync"
 	"sync/atomic"
 
-	lighthousev2a1 "github.com/submariner-io/lighthouse/pkg/apis/lighthouse.submariner.io/v2alpha1"
 	lhconstants "github.com/submariner-io/lighthouse/pkg/constants"
+	mcsv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
 )
 
 type clusterInfo struct {
@@ -102,7 +102,7 @@ func NewMap() *Map {
 	}
 }
 
-func (m *Map) Put(serviceImport *lighthousev2a1.ServiceImport) {
+func (m *Map) Put(serviceImport *mcsv1a1.ServiceImport) {
 	if name, ok := serviceImport.Annotations["origin-name"]; ok {
 		namespace := serviceImport.Annotations["origin-namespace"]
 		key := keyFunc(namespace, name)
@@ -117,11 +117,13 @@ func (m *Map) Put(serviceImport *lighthousev2a1.ServiceImport) {
 				key:        key,
 				clusterIPs: make(map[string]string),
 				rrCount:    0,
-				isHeadless: serviceImport.Spec.Type == lighthousev2a1.Headless,
+				isHeadless: serviceImport.Spec.Type == mcsv1a1.Headless,
 			}
 		}
 
-		remoteService.clusterIPs[serviceImport.GetLabels()[lhconstants.LabelSourceCluster]] = serviceImport.Spec.IP
+		if serviceImport.Spec.Type == mcsv1a1.ClusterSetIP {
+			remoteService.clusterIPs[serviceImport.GetLabels()[lhconstants.LabelSourceCluster]] = serviceImport.Spec.IPs[0]
+		}
 
 		if !remoteService.isHeadless {
 			remoteService.buildClusterInfoQueue()
@@ -131,7 +133,7 @@ func (m *Map) Put(serviceImport *lighthousev2a1.ServiceImport) {
 	}
 }
 
-func (m *Map) Remove(serviceImport *lighthousev2a1.ServiceImport) {
+func (m *Map) Remove(serviceImport *mcsv1a1.ServiceImport) {
 	if name, ok := serviceImport.Annotations["origin-name"]; ok {
 		namespace := serviceImport.Annotations["origin-namespace"]
 		key := keyFunc(namespace, name)
diff --git a/pkg/serviceimport/store.go b/pkg/serviceimport/store.go
index 092a9e6..b563447 100644
--- a/pkg/serviceimport/store.go
+++ b/pkg/serviceimport/store.go
@@ -1,9 +1,9 @@
 package serviceimport
 
-import lighthousev2a1 "github.com/submariner-io/lighthouse/pkg/apis/lighthouse.submariner.io/v2alpha1"
+import mcsv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
 
 type Store interface {
-	Put(serviceImport *lighthousev2a1.ServiceImport)
+	Put(serviceImport *mcsv1a1.ServiceImport)
 
-	Remove(serviceImport *lighthousev2a1.ServiceImport)
+	Remove(serviceImport *mcsv1a1.ServiceImport)
 }


Test patch:
diff --git a/pkg/agent/controller/agent_test.go b/pkg/agent/controller/agent_test.go
index 51f0745..09da206 100644
--- a/pkg/agent/controller/agent_test.go
+++ b/pkg/agent/controller/agent_test.go
@@ -28,6 +28,7 @@ import (
 	"k8s.io/client-go/kubernetes"
 	fakeKubeClient "k8s.io/client-go/kubernetes/fake"
 	"k8s.io/client-go/kubernetes/scheme"
+	mcsv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
 )
 
 const clusterID1 = "east"
@@ -105,12 +106,14 @@ var _ = Describe("ServiceImport syncing", func() {
 			t.createService()
 			t.createServiceExport()
 
-			t.awaitServiceExportStatus(0, newServiceExportCondition(lighthousev2a1.ServiceExportInitialized,
-				corev1.ConditionTrue, "AwaitingSync"))
+			message := "AwaitingSync"
+			t.awaitServiceExportStatus(0, newServiceExportCondition(mcsv1a1.ServiceExportValid,
+				corev1.ConditionTrue, message))
 
-			t.awaitNotServiceExportStatus(&lighthousev2a1.ServiceExportCondition{
-				Type:   lighthousev2a1.ServiceExportExported,
-				Status: corev1.ConditionTrue,
+			t.awaitNotServiceExportStatus(&mcsv1a1.ServiceExportCondition{
+				Type:    mcsv1a1.ServiceExportValid,
+				Status:  corev1.ConditionTrue,
+				Message: &message,
 			})
 
 			t.brokerServiceImportClient.PersistentFailOnCreate.Store("")
@@ -134,7 +137,7 @@ var _ = Describe("ServiceImport syncing", func() {
 			t.createService()
 			t.createServiceExport()
 
-			t.awaitServiceExportStatus(0, newServiceExportCondition(lighthousev2a1.ServiceExportExported,
+			t.awaitServiceExportStatus(0, newServiceExportCondition(mcsv1a1.ServiceExportValid,
 				corev1.ConditionTrue, ""))
 		})
 	})
@@ -148,7 +151,7 @@ var _ = Describe("ServiceImport syncing", func() {
 			t.createService()
 			t.createServiceExport()
 
-			t.awaitServiceExportStatus(0, newServiceExportCondition(lighthousev2a1.ServiceExportInitialized,
+			t.awaitServiceExportStatus(0, newServiceExportCondition(mcsv1a1.ServiceExportValid,
 				corev1.ConditionFalse, "UnsupportedServiceType"))
 			t.awaitNoServiceImport(t.brokerServiceImportClient)
 		})
@@ -187,7 +190,7 @@ var _ = Describe("Globalnet enabled", func() {
 
 	When("a local ServiceExport is created and the Service does not initially have a global IP", func() {
 		It("should eventually sync a ServiceImport with the global IP of the Service", func() {
-			t.awaitServiceExportStatus(0, newServiceExportCondition(lighthousev2a1.ServiceExportInitialized,
+			t.awaitServiceExportStatus(0, newServiceExportCondition(mcsv1a1.ServiceExportValid,
 				corev1.ConditionFalse, "ServiceGlobalIPUnavailable"))
 
 			t.service.SetAnnotations(map[string]string{"submariner.io/globalIp": globalIP})
@@ -203,7 +206,7 @@ var _ = Describe("Globalnet enabled", func() {
 		})
 
 		It("should update the ServiceExport status and not sync a ServiceImport", func() {
-			t.awaitServiceExportStatus(0, newServiceExportCondition(lighthousev2a1.ServiceExportInitialized,
+			t.awaitServiceExportStatus(0, newServiceExportCondition(mcsv1a1.ServiceExportValid,
 				corev1.ConditionFalse, "UnsupportedServiceType"))
 
 			t.awaitNoServiceImport(t.brokerServiceImportClient)
@@ -304,7 +307,7 @@ var _ = Describe("Service export failures", func() {
 		})
 
 		It("should update the ServiceExport status and eventually sync a ServiceImport", func() {
-			t.awaitServiceExportStatus(0, newServiceExportCondition(lighthousev2a1.ServiceExportInitialized,
+			t.awaitServiceExportStatus(0, newServiceExportCondition(mcsv1a1.ServiceExportValid,
 				corev1.ConditionUnknown, "ServiceRetrievalFailed"))
 			t.cluster1.endpointsReactor.SetResetOnFailure(true)
 			t.awaitHeadlessServiceImport("")
@@ -340,7 +343,7 @@ type testDriver struct {
 	brokerServiceImportClient *fake.DynamicResourceClient
 	brokerEndpointSliceClient *fake.DynamicResourceClient
 	service                   *corev1.Service
-	serviceExport             *lighthousev2a1.ServiceExport
+	serviceExport             *mcsv1a1.ServiceExport
 	endpoints                 *corev1.Endpoints
 	stopCh                    chan struct{}
 	restMapper                meta.RESTMapper
@@ -351,6 +354,7 @@ func newTestDiver() *testDriver {
 	syncerScheme := runtime.NewScheme()
 	Expect(corev1.AddToScheme(syncerScheme)).To(Succeed())
 	Expect(discovery.AddToScheme(syncerScheme)).To(Succeed())
+	Expect(mcsv1a1.AddToScheme(syncerScheme)).To(Succeed())
 	Expect(lighthousev2a1.AddToScheme(syncerScheme)).To(Succeed())
 
 	t := &testDriver{
@@ -378,14 +382,14 @@ func newTestDiver() *testDriver {
 				Selector:  map[string]string{"app": "test"},
 			},
 		},
-		restMapper: test.GetRESTMapperFor(&lighthousev2a1.ServiceExport{}, &lighthousev2a1.ServiceImport{},
-			&corev1.Service{}, &corev1.Endpoints{}, &discovery.EndpointSlice{}),
+		restMapper: test.GetRESTMapperFor(&mcsv1a1.ServiceExport{}, &mcsv1a1.ServiceImport{},
+			&corev1.Service{}, &corev1.Endpoints{}, &discovery.EndpointSlice{}, &lighthousev2a1.ServiceExport{}),
 		brokerDynClient: fake.NewDynamicClient(syncerScheme),
 		syncerScheme:    syncerScheme,
 		stopCh:          make(chan struct{}),
 	}
 
-	t.serviceExport = &lighthousev2a1.ServiceExport{
+	t.serviceExport = &mcsv1a1.ServiceExport{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      t.service.Name,
 			Namespace: t.service.Namespace,
@@ -427,7 +431,7 @@ func newTestDiver() *testDriver {
 	}
 
 	t.brokerServiceImportClient = t.brokerDynClient.Resource(*test.GetGroupVersionResourceFor(t.restMapper,
-		&lighthousev2a1.ServiceImport{})).Namespace(test.RemoteNamespace).(*fake.DynamicResourceClient)
+		&mcsv1a1.ServiceImport{})).Namespace(test.RemoteNamespace).(*fake.DynamicResourceClient)
 
 	t.brokerEndpointSliceClient = t.brokerDynClient.Resource(*test.GetGroupVersionResourceFor(t.restMapper,
 		&discovery.EndpointSlice{})).Namespace(test.RemoteNamespace).(*fake.DynamicResourceClient)
@@ -455,10 +459,10 @@ func (c *cluster) init(restMapper meta.RESTMapper, syncerScheme *runtime.Scheme)
 	c.localDynClient = fake.NewDynamicClient(syncerScheme)
 
 	c.localServiceExportClient = c.localDynClient.Resource(*test.GetGroupVersionResourceFor(restMapper,
-		&lighthousev2a1.ServiceExport{})).Namespace(test.LocalNamespace).(*fake.DynamicResourceClient)
+		&mcsv1a1.ServiceExport{})).Namespace(test.LocalNamespace).(*fake.DynamicResourceClient)
 
 	c.localServiceImportClient = c.localDynClient.Resource(*test.GetGroupVersionResourceFor(restMapper,
-		&lighthousev2a1.ServiceImport{})).Namespace(test.LocalNamespace)
+		&mcsv1a1.ServiceImport{})).Namespace(test.LocalNamespace)
 
 	c.localEndpointSliceClient = c.localDynClient.Resource(*test.GetGroupVersionResourceFor(restMapper,
 		&discovery.EndpointSlice{})).Namespace(test.LocalNamespace)
@@ -480,11 +484,11 @@ func (c *cluster) start(t *testDriver, syncerConfig *broker.SyncerConfig, syncer
 	Expect(agentController.Start(t.stopCh)).To(Succeed())
 }
 
-func awaitServiceImport(client dynamic.ResourceInterface, service *corev1.Service, sType lighthousev2a1.ServiceImportType,
-	serviceIP string) *lighthousev2a1.ServiceImport {
+func awaitServiceImport(client dynamic.ResourceInterface, service *corev1.Service, sType mcsv1a1.ServiceImportType,
+	serviceIP string) *mcsv1a1.ServiceImport {
 	obj := test.AwaitResource(client, service.Name+"-"+service.Namespace+"-"+clusterID1)
 
-	serviceImport := &lighthousev2a1.ServiceImport{}
+	serviceImport := &mcsv1a1.ServiceImport{}
 	Expect(scheme.Scheme.Convert(obj, serviceImport, nil)).To(Succeed())
 
 	Expect(serviceImport.GetAnnotations()["origin-name"]).To(Equal(service.Name))
@@ -494,7 +498,12 @@ func awaitServiceImport(client dynamic.ResourceInterface, service *corev1.Servic
 	Expect(serviceImport.Status.Clusters).To(HaveLen(1))
 	Expect(serviceImport.Status.Clusters[0].Cluster).To(Equal(clusterID1))
 
-	Expect(serviceImport.Spec.IP).To(Equal(serviceIP))
+	if serviceIP == "" {
+		Expect(len(serviceImport.Spec.IPs)).To(Equal(0))
+	} else {
+		Expect(serviceImport.Spec.IPs).To(Equal([]string{serviceIP}))
+	}
+
 	labels := serviceImport.GetObjectMeta().GetLabels()
 	Expect(labels[lhconstants.LabelSourceNamespace]).To(Equal(service.GetNamespace()))
 	Expect(labels[lhconstants.LabelSourceName]).To(Equal(service.GetName()))
@@ -503,28 +512,36 @@ func awaitServiceImport(client dynamic.ResourceInterface, service *corev1.Servic
 	return serviceImport
 }
 
-func (c *cluster) awaitServiceImport(service *corev1.Service, sType lighthousev2a1.ServiceImportType, serviceIP string) {
+func (c *cluster) awaitServiceImport(service *corev1.Service, sType mcsv1a1.ServiceImportType, serviceIP string) {
 	awaitServiceImport(c.localServiceImportClient, service, sType, serviceIP)
 }
 
 func awaitUpdatedServiceImport(client dynamic.ResourceInterface, service *corev1.Service,
-	serviceIP string) *lighthousev2a1.ServiceImport {
+	serviceIP string) *mcsv1a1.ServiceImport {
 	name := service.Name + "-" + service.Namespace + "-" + clusterID1
 
-	var serviceImport *lighthousev2a1.ServiceImport
+	var serviceImport *mcsv1a1.ServiceImport
 
 	err := wait.PollImmediate(50*time.Millisecond, 5*time.Second, func() (bool, error) {
 		obj, err := client.Get(name, metav1.GetOptions{})
 		Expect(err).To(Succeed())
 
-		serviceImport = &lighthousev2a1.ServiceImport{}
+		serviceImport = &mcsv1a1.ServiceImport{}
 		Expect(scheme.Scheme.Convert(obj, serviceImport, nil)).To(Succeed())
 
-		return reflect.DeepEqual(serviceImport.Spec.IP, serviceIP), nil
+		if serviceIP == "" {
+			return len(serviceImport.Spec.IPs) == 0, nil
+		} else {
+			return reflect.DeepEqual(serviceImport.Spec.IPs, []string{serviceIP}), nil
+		}
 	})
 
 	if err == wait.ErrWaitTimeout {
-		Expect(serviceImport.Spec.IP).To(Equal(serviceIP))
+		if serviceIP == "" {
+			Expect(len(serviceImport.Spec.IPs)).To(Equal(0))
+		} else {
+			Expect(serviceImport.Spec.IPs).To(Equal([]string{serviceIP}))
+		}
 	}
 
 	Expect(err).To(Succeed())
@@ -643,7 +660,7 @@ func (c *cluster) awaitUpdatedEndpointSlice(endpoints *corev1.Endpoints, expecte
 	awaitUpdatedEndpointSlice(c.localEndpointSliceClient, endpoints, expectedIPs)
 }
 
-func (t *testDriver) awaitBrokerServiceImport(sType lighthousev2a1.ServiceImportType, serviceIP string) {
+func (t *testDriver) awaitBrokerServiceImport(sType mcsv1a1.ServiceImportType, serviceIP string) {
 	awaitServiceImport(t.brokerServiceImportClient, t.service, sType, serviceIP)
 }
 
@@ -716,8 +733,8 @@ func (t *testDriver) awaitNoEndpointSlice(client dynamic.ResourceInterface) {
 	test.AwaitNoResource(client, t.endpoints.Name+"-"+clusterID1)
 }
 
-func (t *testDriver) awaitServiceExportStatus(atIndex int, expCond ...*lighthousev2a1.ServiceExportCondition) {
-	var found *lighthousev2a1.ServiceExport
+func (t *testDriver) awaitServiceExportStatus(atIndex int, expCond ...*mcsv1a1.ServiceExportCondition) {
+	var found *mcsv1a1.ServiceExport
 
 	err := wait.PollImmediate(50*time.Millisecond, 5*time.Second, func() (bool, error) {
 		obj, err := t.cluster1.localServiceExportClient.Get(t.service.Name, metav1.GetOptions{})
@@ -729,7 +746,7 @@ func (t *testDriver) awaitServiceExportStatus(atIndex int, expCond ...*lighthous
 			return false, err
 		}
 
-		se := &lighthousev2a1.ServiceExport{}
+		se := &mcsv1a1.ServiceExport{}
 		Expect(scheme.Scheme.Convert(obj, se, nil)).To(Succeed())
 
 		found = se
@@ -764,7 +781,7 @@ func (t *testDriver) awaitServiceExportStatus(atIndex int, expCond ...*lighthous
 	}
 }
 
-func (t *testDriver) awaitNotServiceExportStatus(notCond *lighthousev2a1.ServiceExportCondition) {
+func (t *testDriver) awaitNotServiceExportStatus(notCond *mcsv1a1.ServiceExportCondition) {
 	err := wait.PollImmediate(50*time.Millisecond, 300*time.Millisecond, func() (bool, error) {
 		obj, err := t.cluster1.localServiceExportClient.Get(t.service.Name, metav1.GetOptions{})
 		if apierrors.IsNotFound(err) {
@@ -775,7 +792,7 @@ func (t *testDriver) awaitNotServiceExportStatus(notCond *lighthousev2a1.Service
 			return false, err
 		}
 
-		se := &lighthousev2a1.ServiceExport{}
+		se := &mcsv1a1.ServiceExport{}
 		Expect(scheme.Scheme.Convert(obj, se, nil)).To(Succeed())
 
 		if len(se.Status.Conditions) == 0 {
@@ -783,7 +800,7 @@ func (t *testDriver) awaitNotServiceExportStatus(notCond *lighthousev2a1.Service
 		}
 
 		last := &se.Status.Conditions[len(se.Status.Conditions)-1]
-		if last.Type == notCond.Type && last.Status == notCond.Status {
+		if last.Message == notCond.Message && last.Status == notCond.Status {
 			return false, fmt.Errorf("Received unexpected %#v", last)
 		}
 
@@ -796,21 +813,21 @@ func (t *testDriver) awaitNotServiceExportStatus(notCond *lighthousev2a1.Service
 }
 
 func (t *testDriver) awaitServiceExported(serviceIP string, statusIndex int) int {
-	t.awaitBrokerServiceImport(lighthousev2a1.ClusterSetIP, serviceIP)
-	t.cluster1.awaitServiceImport(t.service, lighthousev2a1.ClusterSetIP, serviceIP)
-	t.cluster2.awaitServiceImport(t.service, lighthousev2a1.ClusterSetIP, serviceIP)
+	t.awaitBrokerServiceImport(mcsv1a1.ClusterSetIP, serviceIP)
+	t.cluster1.awaitServiceImport(t.service, mcsv1a1.ClusterSetIP, serviceIP)
+	t.cluster2.awaitServiceImport(t.service, mcsv1a1.ClusterSetIP, serviceIP)
 
-	t.awaitServiceExportStatus(statusIndex, newServiceExportCondition(lighthousev2a1.ServiceExportInitialized,
-		corev1.ConditionTrue, "AwaitingSync"), newServiceExportCondition(lighthousev2a1.ServiceExportExported,
+	t.awaitServiceExportStatus(statusIndex, newServiceExportCondition(mcsv1a1.ServiceExportValid,
+		corev1.ConditionTrue, "AwaitingSync"), newServiceExportCondition(mcsv1a1.ServiceExportValid,
 		corev1.ConditionTrue, ""))
 
 	return statusIndex + 2
 }
 
 func (t *testDriver) awaitHeadlessServiceImport(serviceIP string) {
-	t.awaitBrokerServiceImport(lighthousev2a1.Headless, serviceIP)
-	t.cluster1.awaitServiceImport(t.service, lighthousev2a1.Headless, serviceIP)
-	t.cluster2.awaitServiceImport(t.service, lighthousev2a1.Headless, serviceIP)
+	t.awaitBrokerServiceImport(mcsv1a1.Headless, serviceIP)
+	t.cluster1.awaitServiceImport(t.service, mcsv1a1.Headless, serviceIP)
+	t.cluster2.awaitServiceImport(t.service, mcsv1a1.Headless, serviceIP)
 }
 
 func (t *testDriver) awaitServiceUnexported() {
@@ -840,7 +857,7 @@ func (t *testDriver) awaitHeadlessServiceUnexported() {
 }
 
 func (t *testDriver) awaitServiceUnavailableStatus(atIndex int) {
-	t.awaitServiceExportStatus(atIndex, newServiceExportCondition(lighthousev2a1.ServiceExportInitialized,
+	t.awaitServiceExportStatus(atIndex, newServiceExportCondition(mcsv1a1.ServiceExportValid,
 		corev1.ConditionFalse, "ServiceUnavailable"))
 }
 
@@ -853,9 +870,9 @@ func (t *testDriver) endpointIPs() []string {
 	return ips
 }
 
-func newServiceExportCondition(cType lighthousev2a1.ServiceExportConditionType,
-	status corev1.ConditionStatus, reason string) *lighthousev2a1.ServiceExportCondition {
-	return &lighthousev2a1.ServiceExportCondition{
+func newServiceExportCondition(cType mcsv1a1.ServiceExportConditionType,
+	status corev1.ConditionStatus, reason string) *mcsv1a1.ServiceExportCondition {
+	return &mcsv1a1.ServiceExportCondition{
 		Type:   cType,
 		Status: status,
 		Reason: &reason,
diff --git a/pkg/agent/controller/controller_suite_test.go b/pkg/agent/controller/controller_suite_test.go
index daa0ca6..0ed5435 100644
--- a/pkg/agent/controller/controller_suite_test.go
+++ b/pkg/agent/controller/controller_suite_test.go
@@ -8,12 +8,18 @@ import (
 	lighthousev2a1 "github.com/submariner-io/lighthouse/pkg/apis/lighthouse.submariner.io/v2alpha1"
 	"k8s.io/client-go/kubernetes/scheme"
 	"k8s.io/klog"
+	mcsv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
 )
 
 func init() {
 	klog.InitFlags(nil)
 
-	err := lighthousev2a1.AddToScheme(scheme.Scheme)
+	err := mcsv1a1.AddToScheme(scheme.Scheme)
+	if err != nil {
+		panic(err)
+	}
+
+	err = lighthousev2a1.AddToScheme(scheme.Scheme)
 	if err != nil {
 		panic(err)
 	}
diff --git a/pkg/agent/controller/lhserviceexport_test.go b/pkg/agent/controller/lhserviceexport_test.go
new file mode 100644
index 0000000..a0924d9
--- /dev/null
+++ b/pkg/agent/controller/lhserviceexport_test.go
@@ -0,0 +1,135 @@
+package controller
+
+import (
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+	"github.com/submariner-io/admiral/pkg/fake"
+	"github.com/submariner-io/admiral/pkg/syncer/broker"
+	"github.com/submariner-io/admiral/pkg/syncer/test"
+	lighthousev2a1 "github.com/submariner-io/lighthouse/pkg/apis/lighthouse.submariner.io/v2alpha1"
+	corev1 "k8s.io/api/core/v1"
+	discovery "k8s.io/api/discovery/v1beta1"
+	"k8s.io/apimachinery/pkg/api/meta"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/client-go/dynamic"
+	"k8s.io/client-go/kubernetes/scheme"
+	mcsv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
+)
+
+type cluster struct {
+	localDynClient              dynamic.Interface
+	localLhServiceExportClient  *fake.DynamicResourceClient
+	localMcsServiceExportClient *fake.DynamicResourceClient
+}
+
+type testDriver struct {
+	cluster1        cluster
+	brokerDynClient dynamic.Interface
+	serviceExport   *lighthousev2a1.ServiceExport
+	stopCh          chan struct{}
+	restMapper      meta.RESTMapper
+	syncerScheme    *runtime.Scheme
+}
+
+func (t *testDriver) justBeforeEach() {
+	syncerConfig := &broker.SyncerConfig{
+		BrokerNamespace: test.RemoteNamespace,
+	}
+
+	t.cluster1.start(t, syncerConfig, t.syncerScheme)
+}
+
+func (t *testDriver) afterEach() {
+	close(t.stopCh)
+}
+
+func (t *testDriver) createServiceExport() {
+	test.CreateResource(t.cluster1.localLhServiceExportClient, t.serviceExport)
+}
+
+func (c *cluster) start(t *testDriver, syncerConfig *broker.SyncerConfig, syncerScheme *runtime.Scheme) {
+	lhExportController, err := newLHServiceExportController(c.localDynClient, t.restMapper, syncerScheme)
+
+	Expect(err).To(Succeed())
+	Expect(lhExportController.start(t.stopCh)).To(Succeed())
+}
+
+var _ = Describe("ServiceImport syncing", func() {
+	var t *testDriver
+
+	BeforeEach(func() {
+		t = newTestDriver()
+	})
+
+	JustBeforeEach(func() {
+		t.justBeforeEach()
+	})
+
+	AfterEach(func() {
+		t.afterEach()
+	})
+
+	When("a ServiceExport is created", func() {
+		When("the Service already exists", func() {
+			It("should correctly sync a ServiceImport and update the ServiceExport status", func() {
+				t.createServiceExport()
+				t.awaitNoLHServiceexport(t.cluster1.localLhServiceExportClient)
+				t.awaitMcsService(t.cluster1.localMcsServiceExportClient, t.serviceExport)
+			})
+		})
+	})
+})
+
+func newTestDriver() *testDriver {
+	syncerScheme := runtime.NewScheme()
+	Expect(corev1.AddToScheme(syncerScheme)).To(Succeed())
+	Expect(discovery.AddToScheme(syncerScheme)).To(Succeed())
+	Expect(mcsv1a1.AddToScheme(syncerScheme)).To(Succeed())
+	Expect(lighthousev2a1.AddToScheme(syncerScheme)).To(Succeed())
+
+	t := &testDriver{
+		cluster1:        cluster{},
+		restMapper:      test.GetRESTMapperFor(&mcsv1a1.ServiceExport{}, &lighthousev2a1.ServiceExport{}),
+		brokerDynClient: fake.NewDynamicClient(syncerScheme),
+		syncerScheme:    syncerScheme,
+		stopCh:          make(chan struct{}),
+	}
+
+	t.serviceExport = &lighthousev2a1.ServiceExport{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "service1",
+			Namespace: test.LocalNamespace,
+		},
+	}
+
+	t.cluster1.init(t.restMapper, syncerScheme)
+
+	return t
+}
+
+func (c *cluster) init(restMapper meta.RESTMapper, syncerScheme *runtime.Scheme) {
+	c.localDynClient = fake.NewDynamicClient(syncerScheme)
+
+	c.localLhServiceExportClient = c.localDynClient.Resource(*test.GetGroupVersionResourceFor(restMapper,
+		&lighthousev2a1.ServiceExport{})).Namespace(test.LocalNamespace).(*fake.DynamicResourceClient)
+
+	c.localMcsServiceExportClient = c.localDynClient.Resource(*test.GetGroupVersionResourceFor(restMapper,
+		&mcsv1a1.ServiceExport{})).Namespace(test.LocalNamespace).(*fake.DynamicResourceClient)
+}
+
+func (t *testDriver) awaitMcsService(client dynamic.ResourceInterface, serviceExport *lighthousev2a1.ServiceExport) *mcsv1a1.ServiceExport {
+	obj := test.AwaitResource(client, serviceExport.Name)
+
+	mcsServiceExport := &mcsv1a1.ServiceExport{}
+	Expect(scheme.Scheme.Convert(obj, mcsServiceExport, nil)).To(Succeed())
+
+	Expect(mcsServiceExport.GetObjectMeta().GetName()).To(Equal(serviceExport.GetObjectMeta().GetName()))
+	Expect(mcsServiceExport.GetObjectMeta().GetNamespace()).To(Equal(serviceExport.GetObjectMeta().GetNamespace()))
+
+	return mcsServiceExport
+}
+
+func (t *testDriver) awaitNoLHServiceexport(client dynamic.ResourceInterface) {
+	test.AwaitNoResource(client, "service1")
+}
diff --git a/pkg/serviceimport/controller_test.go b/pkg/serviceimport/controller_test.go
index f5ed157..1c0d20d 100644
--- a/pkg/serviceimport/controller_test.go
+++ b/pkg/serviceimport/controller_test.go
@@ -3,13 +3,13 @@ package serviceimport_test
 import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
-	lighthousev2a1 "github.com/submariner-io/lighthouse/pkg/apis/lighthouse.submariner.io/v2alpha1"
-	lighthouseClientset "github.com/submariner-io/lighthouse/pkg/client/clientset/versioned"
-	fakeClientSet "github.com/submariner-io/lighthouse/pkg/client/clientset/versioned/fake"
 	lhconstants "github.com/submariner-io/lighthouse/pkg/constants"
+	mcsClientset "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned"
+	fakeMCSClientSet "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned/fake"
 	"github.com/submariner-io/lighthouse/pkg/serviceimport"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/rest"
+	mcsv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
 )
 
 var _ = Describe("ServiceImport controller", func() {
@@ -27,24 +27,24 @@ func testLifecycleNotifications() {
 	)
 
 	var (
-		serviceImport *lighthousev2a1.ServiceImport
+		serviceImport *mcsv1a1.ServiceImport
 		controller    *serviceimport.Controller
-		fakeClientset lighthouseClientset.Interface
+		fakeClientSet mcsClientset.Interface
 		store         *fakeStore
 	)
 
 	BeforeEach(func() {
 		store = &fakeStore{
-			put:    make(chan *lighthousev2a1.ServiceImport, 10),
-			remove: make(chan *lighthousev2a1.ServiceImport, 10),
+			put:    make(chan *mcsv1a1.ServiceImport, 10),
+			remove: make(chan *mcsv1a1.ServiceImport, 10),
 		}
 
 		serviceImport = newServiceImport(namespace1, service1, serviceIP, clusterID)
 		controller = serviceimport.NewController(store)
-		fakeClientset = fakeClientSet.NewSimpleClientset()
+		fakeClientSet = fakeMCSClientSet.NewSimpleClientset()
 
-		controller.NewClientset = func(c *rest.Config) (lighthouseClientset.Interface, error) {
-			return fakeClientset, nil
+		controller.NewClientset = func(c *rest.Config) (mcsClientset.Interface, error) {
+			return fakeClientSet, nil
 		}
 
 		Expect(controller.Start(&rest.Config{})).To(Succeed())
@@ -54,39 +54,39 @@ func testLifecycleNotifications() {
 		controller.Stop()
 	})
 
-	createService := func(serviceImport *lighthousev2a1.ServiceImport) error {
-		_, err := fakeClientset.LighthouseV2alpha1().ServiceImports(serviceImport.Namespace).Create(serviceImport)
+	createService := func(serviceImport *mcsv1a1.ServiceImport) error {
+		_, err := fakeClientSet.MulticlusterV1alpha1().ServiceImports(serviceImport.Namespace).Create(serviceImport)
 		return err
 	}
 
-	updateService := func(serviceImport *lighthousev2a1.ServiceImport) error {
-		_, err := fakeClientset.LighthouseV2alpha1().ServiceImports(serviceImport.Namespace).Update(serviceImport)
+	updateService := func(serviceImport *mcsv1a1.ServiceImport) error {
+		_, err := fakeClientSet.MulticlusterV1alpha1().ServiceImports(serviceImport.Namespace).Update(serviceImport)
 		return err
 	}
 
-	deleteService := func(serviceImport *lighthousev2a1.ServiceImport) error {
-		err := fakeClientset.LighthouseV2alpha1().ServiceImports(serviceImport.Namespace).Delete(serviceImport.Name, &metav1.DeleteOptions{})
+	deleteService := func(serviceImport *mcsv1a1.ServiceImport) error {
+		err := fakeClientSet.MulticlusterV1alpha1().ServiceImports(serviceImport.Namespace).Delete(serviceImport.Name, &metav1.DeleteOptions{})
 		return err
 	}
 
-	testOnAdd := func(serviceImport *lighthousev2a1.ServiceImport) {
+	testOnAdd := func(serviceImport *mcsv1a1.ServiceImport) {
 		Expect(createService(serviceImport)).To(Succeed())
 		store.verifyPut(serviceImport)
 	}
 
-	testOnUpdate := func(serviceImport *lighthousev2a1.ServiceImport) {
+	testOnUpdate := func(serviceImport *mcsv1a1.ServiceImport) {
 		Expect(updateService(serviceImport)).To(Succeed())
 		store.verifyPut(serviceImport)
 	}
 
-	testOnRemove := func(serviceImport *lighthousev2a1.ServiceImport) {
+	testOnRemove := func(serviceImport *mcsv1a1.ServiceImport) {
 		testOnAdd(serviceImport)
 
 		Expect(deleteService(serviceImport)).To(Succeed())
 		store.verifyRemove(serviceImport)
 	}
 
-	testOnDoubleAdd := func(first *lighthousev2a1.ServiceImport, second *lighthousev2a1.ServiceImport) {
+	testOnDoubleAdd := func(first *mcsv1a1.ServiceImport, second *mcsv1a1.ServiceImport) {
 		Expect(createService(first)).To(Succeed())
 		Expect(createService(second)).To(Succeed())
 
@@ -120,8 +120,8 @@ func testLifecycleNotifications() {
 	})
 }
 
-func newServiceImport(namespace, name, serviceIP, clusterID string) *lighthousev2a1.ServiceImport {
-	return &lighthousev2a1.ServiceImport{
+func newServiceImport(namespace, name, serviceIP, clusterID string) *mcsv1a1.ServiceImport {
+	return &mcsv1a1.ServiceImport{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      name + "-" + namespace + "-" + clusterID,
 			Namespace: namespace,
@@ -133,12 +133,12 @@ func newServiceImport(namespace, name, serviceIP, clusterID string) *lighthousev
 				lhconstants.LabelSourceCluster: clusterID,
 			},
 		},
-		Spec: lighthousev2a1.ServiceImportSpec{
-			Type: lighthousev2a1.ClusterSetIP,
-			IP:   serviceIP,
+		Spec: mcsv1a1.ServiceImportSpec{
+			Type: mcsv1a1.ClusterSetIP,
+			IPs:  []string{serviceIP},
 		},
-		Status: lighthousev2a1.ServiceImportStatus{
-			Clusters: []lighthousev2a1.ClusterStatus{
+		Status: mcsv1a1.ServiceImportStatus{
+			Clusters: []mcsv1a1.ClusterStatus{
 				{
 					Cluster: clusterID,
 				},
@@ -148,22 +148,22 @@ func newServiceImport(namespace, name, serviceIP, clusterID string) *lighthousev
 }
 
 type fakeStore struct {
-	put    chan *lighthousev2a1.ServiceImport
-	remove chan *lighthousev2a1.ServiceImport
+	put    chan *mcsv1a1.ServiceImport
+	remove chan *mcsv1a1.ServiceImport
 }
 
-func (f *fakeStore) Put(si *lighthousev2a1.ServiceImport) {
+func (f *fakeStore) Put(si *mcsv1a1.ServiceImport) {
 	f.put <- si
 }
 
-func (f *fakeStore) Remove(si *lighthousev2a1.ServiceImport) {
+func (f *fakeStore) Remove(si *mcsv1a1.ServiceImport) {
 	f.remove <- si
 }
 
-func (f *fakeStore) verifyPut(expected *lighthousev2a1.ServiceImport) {
+func (f *fakeStore) verifyPut(expected *mcsv1a1.ServiceImport) {
 	Eventually(f.put, 5).Should(Receive(Equal(expected)), "Put was not called")
 }
 
-func (f *fakeStore) verifyRemove(expected *lighthousev2a1.ServiceImport) {
+func (f *fakeStore) verifyRemove(expected *mcsv1a1.ServiceImport) {
 	Eventually(f.remove, 5).Should(Receive(Equal(expected)), "Remove was not called")
 }
diff --git a/plugin/lighthouse/handler_test.go b/plugin/lighthouse/handler_test.go
index 477bc77..1f02c11 100644
--- a/plugin/lighthouse/handler_test.go
+++ b/plugin/lighthouse/handler_test.go
@@ -10,12 +10,12 @@ import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 	"github.com/pkg/errors"
-	lighthousev2a1 "github.com/submariner-io/lighthouse/pkg/apis/lighthouse.submariner.io/v2alpha1"
 	lhconstants "github.com/submariner-io/lighthouse/pkg/constants"
 	"github.com/submariner-io/lighthouse/pkg/endpointslice"
 	"github.com/submariner-io/lighthouse/pkg/serviceimport"
 	discovery "k8s.io/api/discovery/v1beta1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	mcsv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
 )
 
 const (
@@ -127,7 +127,7 @@ func testWithoutFallback() {
 
 	When("type A DNS query for an existing service with a different namespace", func() {
 		It("should succeed and write an A record response", func() {
-			lh.serviceImports.Put(newServiceImport(namespace2, service1, clusterID, serviceIP, lighthousev2a1.ClusterSetIP))
+			lh.serviceImports.Put(newServiceImport(namespace2, service1, clusterID, serviceIP, mcsv1a1.ClusterSetIP))
 			executeTestCase(lh, rec, test.Case{
 				Qname: service1 + "." + namespace2 + ".svc.clusterset.local.",
 				Qtype: dns.TypeA,
@@ -305,7 +305,7 @@ func testClusterStatus() {
 			endpointsStatus: mockEs,
 			ttl:             defaultTtl,
 		}
-		lh.serviceImports.Put(newServiceImport(namespace1, service1, clusterID2, serviceIP2, lighthousev2a1.ClusterSetIP))
+		lh.serviceImports.Put(newServiceImport(namespace1, service1, clusterID2, serviceIP2, mcsv1a1.ClusterSetIP))
 
 		rec = dnstest.NewRecorder(&test.ResponseWriter{})
 	})
@@ -415,7 +415,7 @@ func testHeadlessService() {
 
 	When("headless service has no IPs", func() {
 		JustBeforeEach(func() {
-			lh.serviceImports.Put(newServiceImport(namespace1, service1, clusterID, "", lighthousev2a1.Headless))
+			lh.serviceImports.Put(newServiceImport(namespace1, service1, clusterID, "", mcsv1a1.Headless))
 			lh.endpointSlices.Put(newEndpointSlice(namespace1, service1, clusterID, []string{}))
 		})
 		It("should succeed and return empty response (NODATA)", func() {
@@ -430,7 +430,7 @@ func testHeadlessService() {
 
 	When("headless service has one IP", func() {
 		JustBeforeEach(func() {
-			lh.serviceImports.Put(newServiceImport(namespace1, service1, clusterID, "", lighthousev2a1.Headless))
+			lh.serviceImports.Put(newServiceImport(namespace1, service1, clusterID, "", mcsv1a1.Headless))
 			lh.endpointSlices.Put(newEndpointSlice(namespace1, service1, clusterID, []string{endpointIP}))
 		})
 		It("should succeed and write an A record response", func() {
@@ -447,7 +447,7 @@ func testHeadlessService() {
 
 	When("headless service has two IPs", func() {
 		JustBeforeEach(func() {
-			lh.serviceImports.Put(newServiceImport(namespace1, service1, clusterID, "", lighthousev2a1.Headless))
+			lh.serviceImports.Put(newServiceImport(namespace1, service1, clusterID, "", mcsv1a1.Headless))
 			lh.endpointSlices.Put(newEndpointSlice(namespace1, service1, clusterID, []string{endpointIP, endpointIP2}))
 		})
 		It("should succeed and write two A records as response", func() {
@@ -465,8 +465,8 @@ func testHeadlessService() {
 
 	When("headless service is present in two clusters", func() {
 		JustBeforeEach(func() {
-			lh.serviceImports.Put(newServiceImport(namespace1, service1, clusterID, "", lighthousev2a1.Headless))
-			lh.serviceImports.Put(newServiceImport(namespace1, service1, clusterID2, "", lighthousev2a1.Headless))
+			lh.serviceImports.Put(newServiceImport(namespace1, service1, clusterID, "", mcsv1a1.Headless))
+			lh.serviceImports.Put(newServiceImport(namespace1, service1, clusterID2, "", mcsv1a1.Headless))
 			lh.endpointSlices.Put(newEndpointSlice(namespace1, service1, clusterID, []string{endpointIP}))
 			lh.endpointSlices.Put(newEndpointSlice(namespace1, service1, clusterID2, []string{endpointIP2}))
 			mockCs.clusterStatusMap[clusterID2] = true
@@ -514,7 +514,7 @@ func executeTestCase(lh *Lighthouse, rec *dnstest.Recorder, tc test.Case) {
 
 func setupServiceImportMap() *serviceimport.Map {
 	siMap := serviceimport.NewMap()
-	siMap.Put(newServiceImport(namespace1, service1, clusterID, serviceIP, lighthousev2a1.ClusterSetIP))
+	siMap.Put(newServiceImport(namespace1, service1, clusterID, serviceIP, mcsv1a1.ClusterSetIP))
 
 	return siMap
 }
@@ -527,8 +527,8 @@ func setupEndpointSliceMap() *endpointslice.Map {
 }
 
 func newServiceImport(namespace, name, clusterID, serviceIP string,
-	siType lighthousev2a1.ServiceImportType) *lighthousev2a1.ServiceImport {
-	return &lighthousev2a1.ServiceImport{
+	siType mcsv1a1.ServiceImportType) *mcsv1a1.ServiceImport {
+	return &mcsv1a1.ServiceImport{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      name,
 			Namespace: namespace,
@@ -540,12 +540,12 @@ func newServiceImport(namespace, name, clusterID, serviceIP string,
 				lhconstants.LabelSourceCluster: clusterID,
 			},
 		},
-		Spec: lighthousev2a1.ServiceImportSpec{
+		Spec: mcsv1a1.ServiceImportSpec{
 			Type: siType,
-			IP:   serviceIP,
+			IPs:  []string{serviceIP},
 		},
-		Status: lighthousev2a1.ServiceImportStatus{
-			Clusters: []lighthousev2a1.ClusterStatus{
+		Status: mcsv1a1.ServiceImportStatus{
+			Clusters: []mcsv1a1.ClusterStatus{
 				{
 					Cluster: clusterID,
 				},
diff --git a/plugin/lighthouse/setup_test.go b/plugin/lighthouse/setup_test.go
index cf3b81b..c775abd 100644
--- a/plugin/lighthouse/setup_test.go
+++ b/plugin/lighthouse/setup_test.go
@@ -12,10 +12,10 @@ import (
 	"github.com/miekg/dns"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
-	lighthouseClientset "github.com/submariner-io/lighthouse/pkg/client/clientset/versioned"
-	fakeLighthouseClientset "github.com/submariner-io/lighthouse/pkg/client/clientset/versioned/fake"
 	"github.com/submariner-io/lighthouse/pkg/endpointslice"
 	"github.com/submariner-io/lighthouse/pkg/gateway"
+	mcsClientset "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned"
+	fakeMCSClientset "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned/fake"
 	"github.com/submariner-io/lighthouse/pkg/serviceimport"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/client-go/dynamic"
@@ -41,8 +41,8 @@ var _ = Describe("Plugin setup", func() {
 			return fakeClient.NewSimpleDynamicClient(runtime.NewScheme()), nil
 		}
 
-		serviceimport.NewClientset = func(kubeConfig *rest.Config) (lighthouseClientset.Interface, error) {
-			return fakeLighthouseClientset.NewSimpleClientset(), nil
+		serviceimport.NewClientset = func(kubeConfig *rest.Config) (mcsClientset.Interface, error) {
+			return fakeMCSClientset.NewSimpleClientset(), nil
 		}
 
 		endpointslice.NewClientset = func(kubeConfig *rest.Config) (kubernetes.Interface, error) {
diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go
index 6c22825..66fed07 100644
--- a/test/e2e/framework/framework.go
+++ b/test/e2e/framework/framework.go
@@ -14,10 +14,10 @@ import (
 	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/client-go/rest"
+	mcsv1a1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
 
-	lighthousev2a1 "github.com/submariner-io/lighthouse/pkg/apis/lighthouse.submariner.io/v2alpha1"
-	lighthouseClientset "github.com/submariner-io/lighthouse/pkg/client/clientset/versioned"
 	lhconstants "github.com/submariner-io/lighthouse/pkg/constants"
+	mcsClientset "github.com/submariner-io/lighthouse/pkg/mcs/client/clientset/versioned"
 )
 
 const (
@@ -34,7 +34,7 @@ type Framework struct {
 	*framework.Framework
 }
 
-var LighthouseClients []*lighthouseClientset.Clientset
+var MCSClients []*mcsClientset.Clientset
 
 func init() {
 	framework.AddBeforeSuite(beforeSuite)
@@ -50,45 +50,45 @@ func beforeSuite() {
 	framework.By("Creating lighthouse clients")
 
 	for _, restConfig := range framework.RestConfigs {
-		LighthouseClients = append(LighthouseClients, createLighthouseClient(restConfig))
+		MCSClients = append(MCSClients, createLighthouseClient(restConfig))
 	}
 }
 
-func createLighthouseClient(restConfig *rest.Config) *lighthouseClientset.Clientset {
-	clientSet, err := lighthouseClientset.NewForConfig(restConfig)
+func createLighthouseClient(restConfig *rest.Config) *mcsClientset.Clientset {
+	clientSet, err := mcsClientset.NewForConfig(restConfig)
 	Expect(err).To(Not(HaveOccurred()))
 
 	return clientSet
 }
 
-func (f *Framework) NewServiceExport(cluster framework.ClusterIndex, name, namespace string) *lighthousev2a1.ServiceExport {
-	nginxServiceExport := lighthousev2a1.ServiceExport{
+func (f *Framework) NewServiceExport(cluster framework.ClusterIndex, name, namespace string) *mcsv1a1.ServiceExport {
+	nginxServiceExport := mcsv1a1.ServiceExport{
 		ObjectMeta: metav1.ObjectMeta{
 			Name: name,
 		},
 	}
-	se := LighthouseClients[cluster].LighthouseV2alpha1().ServiceExports(namespace)
+	se := MCSClients[cluster].MulticlusterV1alpha1().ServiceExports(namespace)
 	By(fmt.Sprintf("Creating serviceExport %s.%s on %q", name, namespace, framework.TestContext.ClusterIDs[cluster]))
 	serviceExport := framework.AwaitUntil("create serviceExport", func() (interface{}, error) {
 		return se.Create(&nginxServiceExport)
-	}, framework.NoopCheckResult).(*lighthousev2a1.ServiceExport)
+	}, framework.NoopCheckResult).(*mcsv1a1.ServiceExport)
 
 	return serviceExport
 }
 
 func (f *Framework) AwaitServiceExportedStatusCondition(cluster framework.ClusterIndex, name, namespace string) {
-	se := LighthouseClients[cluster].LighthouseV2alpha1().ServiceExports(namespace)
+	se := MCSClients[cluster].MulticlusterV1alpha1().ServiceExports(namespace)
 	By(fmt.Sprintf("Retrieving ServiceExport %s.%s on %q", name, namespace, framework.TestContext.ClusterIDs[cluster]))
 	framework.AwaitUntil("retrieve ServiceExport", func() (interface{}, error) {
 		return se.Get(name, metav1.GetOptions{})
 	}, func(result interface{}) (bool, string, error) {
-		se := result.(*lighthousev2a1.ServiceExport)
+		se := result.(*mcsv1a1.ServiceExport)
 		if len(se.Status.Conditions) == 0 {
 			return false, "No ServiceExportConditions", nil
 		}
 
 		last := se.Status.Conditions[len(se.Status.Conditions)-1]
-		if last.Type != lighthousev2a1.ServiceExportExported {
+		if last.Type != mcsv1a1.ServiceExportValid {
 			return false, fmt.Sprintf("ServiceExportCondition Type is %v", last.Type), nil
 		}
 
@@ -103,7 +103,7 @@ func (f *Framework) AwaitServiceExportedStatusCondition(cluster framework.Cluste
 func (f *Framework) DeleteServiceExport(cluster framework.ClusterIndex, name, namespace string) {
 	By(fmt.Sprintf("Deleting serviceExport %s.%s on %q", name, namespace, framework.TestContext.ClusterIDs[cluster]))
 	framework.AwaitUntil("delete service export", func() (interface{}, error) {
-		return nil, LighthouseClients[cluster].LighthouseV2alpha1().ServiceExports(namespace).Delete(name, &metav1.DeleteOptions{})
+		return nil, MCSClients[cluster].MulticlusterV1alpha1().ServiceExports(namespace).Delete(name, &metav1.DeleteOptions{})
 	}, framework.NoopCheckResult)
 }
 
@@ -112,7 +112,7 @@ func (f *Framework) GetService(cluster framework.ClusterIndex, name, namespace s
 	return framework.KubeClients[cluster].CoreV1().Services(namespace).Get(name, metav1.GetOptions{})
 }
 
-func (f *Framework) AwaitServiceImportIP(targetCluster framework.ClusterIndex, svc *v1.Service) *lighthousev2a1.ServiceImport {
+func (f *Framework) AwaitServiceImportIP(targetCluster framework.ClusterIndex, svc *v1.Service) *mcsv1a1.ServiceImport {
 	var serviceIP string
 
 	if framework.TestContext.GlobalnetEnabled {
@@ -121,20 +121,20 @@ func (f *Framework) AwaitServiceImportIP(targetCluster framework.ClusterIndex, s
 		serviceIP = svc.Spec.ClusterIP
 	}
 
-	var retServiceImport *lighthousev2a1.ServiceImport
+	var retServiceImport *mcsv1a1.ServiceImport
 
 	siNamePrefix := svc.Name + "-" + svc.Namespace + "-"
-	si := LighthouseClients[targetCluster].LighthouseV2alpha1().ServiceImports(framework.TestContext.SubmarinerNamespace)
+	si := MCSClients[targetCluster].MulticlusterV1alpha1().ServiceImports(framework.TestContext.SubmarinerNamespace)
 	By(fmt.Sprintf("Retrieving ServiceImport for %s on %q", siNamePrefix, framework.TestContext.ClusterIDs[targetCluster]))
 	framework.AwaitUntil("retrieve ServiceImport", func() (interface{}, error) {
 		return si.List(metav1.ListOptions{})
 	}, func(result interface{}) (bool, string, error) {
-		siList := result.(*lighthousev2a1.ServiceImportList)
+		siList := result.(*mcsv1a1.ServiceImportList)
 		for i, si := range siList.Items {
 			if strings.HasPrefix(si.Name, siNamePrefix) {
-				if si.Spec.IP != serviceIP {
+				if si.Spec.IPs[0] != serviceIP {
 					return false, fmt.Sprintf("ServiceImport IP %s doesn't match %s",
-						si.Spec.IP, serviceIP), nil
+						si.Spec.IPs[0], serviceIP), nil
 				}
 				retServiceImport = &siList.Items[i]
 				return true, "", nil
@@ -149,11 +149,11 @@ func (f *Framework) AwaitServiceImportIP(targetCluster framework.ClusterIndex, s
 
 func (f *Framework) AwaitServiceImportDelete(targetCluster framework.ClusterIndex, name, namespace string) {
 	siNamePrefix := name + "-" + namespace
-	si := LighthouseClients[targetCluster].LighthouseV2alpha1().ServiceImports(framework.TestContext.SubmarinerNamespace)
+	si := MCSClients[targetCluster].MulticlusterV1alpha1().ServiceImports(framework.TestContext.SubmarinerNamespace)
 	framework.AwaitUntil("retrieve ServiceImport", func() (interface{}, error) {
 		return si.List(metav1.ListOptions{})
 	}, func(result interface{}) (bool, string, error) {
-		siList := result.(*lighthousev2a1.ServiceImportList)
+		siList := result.(*mcsv1a1.ServiceImportList)
 		for _, si := range siList.Items {
 			if strings.HasPrefix(si.Name, siNamePrefix) {
 				return false, fmt.Sprintf("ServiceImport with name prefix %s still exists", siNamePrefix), nil
@@ -172,11 +172,11 @@ func (f *Framework) AwaitServiceImportCount(targetCluster framework.ClusterIndex
 	siListOptions := metav1.ListOptions{
 		LabelSelector: labels.Set(labelMap).String(),
 	}
-	si := LighthouseClients[targetCluster].LighthouseV2alpha1().ServiceImports(framework.TestContext.SubmarinerNamespace)
+	si := MCSClients[targetCluster].MulticlusterV1alpha1().ServiceImports(framework.TestContext.SubmarinerNamespace)
 	framework.AwaitUntil("retrieve ServiceImport", func() (interface{}, error) {
 		return si.List(siListOptions)
 	}, func(result interface{}) (bool, string, error) {
-		siList := result.(*lighthousev2a1.ServiceImportList)
+		siList := result.(*mcsv1a1.ServiceImportList)
 		if len(siList.Items) != count {
 			return false, fmt.Sprintf("ServiceImport count was %v instead of %v", len(siList.Items), count), nil
 		}