Skip to content

Commit

Permalink
api: define API for MultiClusterService
Browse files Browse the repository at this point in the history
Signed-off-by: jwcesign <[email protected]>
  • Loading branch information
jwcesign committed Nov 23, 2023
1 parent 5b8a7f7 commit 23abfd4
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 23 deletions.
18 changes: 17 additions & 1 deletion api/openapi-spec/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -21169,10 +21169,26 @@
}
},
"range": {
"description": "Range specifies the ranges where the referencing service should be exposed. Only valid and optional in case of Types contains CrossCluster. If not set and Types contains CrossCluster, all clusters will be selected, that means the referencing service will be exposed across all registered clusters.",
"description": "Range specifies the ranges where the referencing service should be exposed. Only valid and optional in case of Types contains CrossCluster. If not set and Types contains CrossCluster, all clusters will be selected, that means the referencing service will be exposed across all registered clusters. Deprecated: in favor of ServiceProvisionClusters/ServiceConsumptionClusters.",
"default": {},
"$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.networking.v1alpha1.ExposureRange"
},
"serviceConsumptionClusters": {
"description": "ServiceConsumptionClusters specifies the clusters where the service will be exposed, for clients. If leave it empty, the service will be exposed to all clusters.",
"type": "array",
"items": {
"type": "string",
"default": ""
}
},
"serviceProvisionClusters": {
"description": "ServiceProvisionClusters specifies the clusters which will provision the service backend. If leave it empty, we will collect the backend endpoints from all clusters and sync them to the ServiceConsumptionClusters.",
"type": "array",
"items": {
"type": "string",
"default": ""
}
},
"types": {
"description": "Types specifies how to expose the service referencing by this MultiClusterService.",
"type": "array",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,32 @@ spec:
type: object
type: array
range:
description: Range specifies the ranges where the referencing service
description: 'Range specifies the ranges where the referencing service
should be exposed. Only valid and optional in case of Types contains
CrossCluster. If not set and Types contains CrossCluster, all clusters
will be selected, that means the referencing service will be exposed
across all registered clusters.
across all registered clusters. Deprecated: in favor of ServiceProvisionClusters/ServiceConsumptionClusters.'
properties:
clusterNames:
description: ClusterNames is the list of clusters to be selected.
items:
type: string
type: array
type: object
serviceConsumptionClusters:
description: ServiceConsumptionClusters specifies the clusters where
the service will be exposed, for clients. If leave it empty, the
service will be exposed to all clusters.
items:
type: string
type: array
serviceProvisionClusters:
description: ServiceProvisionClusters specifies the clusters which
will provision the service backend. If leave it empty, we will collect
the backend endpoints from all clusters and sync them to the ServiceConsumptionClusters.
items:
type: string
type: array
types:
description: Types specifies how to expose the service referencing
by this MultiClusterService.
Expand Down
12 changes: 12 additions & 0 deletions pkg/apis/networking/v1alpha1/service_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,20 @@ type MultiClusterServiceSpec struct {
// If not set and Types contains CrossCluster, all clusters will
// be selected, that means the referencing service will be exposed
// across all registered clusters.
// Deprecated: in favor of ServiceProvisionClusters/ServiceConsumptionClusters.
// +optional
Range ExposureRange `json:"range,omitempty"`

// ServiceProvisionClusters specifies the clusters which will provision the service backend.
// If leave it empty, we will collect the backend endpoints from all clusters and sync
// them to the ServiceConsumptionClusters.
// +optional
ServiceProvisionClusters []string `json:"serviceProvisionClusters,omitempty"`

// ServiceConsumptionClusters specifies the clusters where the service will be exposed, for clients.
// If leave it empty, the service will be exposed to all clusters.
// +optional
ServiceConsumptionClusters []string `json:"serviceConsumptionClusters,omitempty"`
}

// ExposureType describes how to expose the service.
Expand Down
10 changes: 10 additions & 0 deletions pkg/apis/networking/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 31 additions & 1 deletion pkg/generated/openapi/zz_generated.openapi.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 12 additions & 3 deletions pkg/webhook/multiclusterservice/validating.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,19 @@ func (v *ValidatingAdmission) validateMultiClusterServiceSpec(mcs *networkingv1a
exposureType := mcs.Spec.Types[i]
allErrs = append(allErrs, v.validateExposureType(&exposureType, typePath)...)
}
clusterNamesPath := specPath.Child("range").Child("clusterNames")
for i := range mcs.Spec.Range.ClusterNames {
clusterNamesPath := specPath.Child("range").Child("serverLocaltions")
for i := range mcs.Spec.ServiceProvisionClusters {
clusterNamePath := clusterNamesPath.Index(i)
clusterName := mcs.Spec.Range.ClusterNames[i]
clusterName := mcs.Spec.ServiceProvisionClusters[i]
if errMegs := clustervalidation.ValidateClusterName(clusterName); len(errMegs) > 0 {
allErrs = append(allErrs, field.Invalid(clusterNamePath, clusterName, strings.Join(errMegs, ",")))
}
}

clusterNamesPath = specPath.Child("range").Child("cllientLocaltions")
for i := range mcs.Spec.ServiceConsumptionClusters {
clusterNamePath := clusterNamesPath.Index(i)
clusterName := mcs.Spec.ServiceConsumptionClusters[i]
if errMegs := clustervalidation.ValidateClusterName(clusterName); len(errMegs) > 0 {
allErrs = append(allErrs, field.Invalid(clusterNamePath, clusterName, strings.Join(errMegs, ",")))
}
Expand Down
27 changes: 11 additions & 16 deletions pkg/webhook/multiclusterservice/validating_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,8 @@ func TestValidateMultiClusterServiceSpec(t *testing.T) {
networkingv1alpha1.ExposureTypeLoadBalancer,
networkingv1alpha1.ExposureTypeCrossCluster,
},
Range: networkingv1alpha1.ExposureRange{
ClusterNames: []string{"member1", "member2"},
},
ServiceProvisionClusters: []string{"member1", "member2"},
ServiceConsumptionClusters: []string{"member1", "member2"},
},
},
expectedErr: field.ErrorList{},
Expand All @@ -78,9 +77,8 @@ func TestValidateMultiClusterServiceSpec(t *testing.T) {
networkingv1alpha1.ExposureTypeLoadBalancer,
networkingv1alpha1.ExposureTypeLoadBalancer,
},
Range: networkingv1alpha1.ExposureRange{
ClusterNames: []string{"member1"},
},
ServiceProvisionClusters: []string{"member1", "member2"},
ServiceConsumptionClusters: []string{"member1", "member2"},
},
},
expectedErr: field.ErrorList{field.Duplicate(specFld.Child("ports").Index(1).Child("name"), "foo")},
Expand All @@ -98,9 +96,8 @@ func TestValidateMultiClusterServiceSpec(t *testing.T) {
Types: []networkingv1alpha1.ExposureType{
networkingv1alpha1.ExposureTypeLoadBalancer,
},
Range: networkingv1alpha1.ExposureRange{
ClusterNames: []string{"member1"},
},
ServiceProvisionClusters: []string{"member1", "member2"},
ServiceConsumptionClusters: []string{"member1", "member2"},
},
},
expectedErr: field.ErrorList{field.Invalid(specFld.Child("ports").Index(0).Child("port"), int32(163121), validation.InclusiveRangeError(1, 65535))},
Expand All @@ -118,9 +115,8 @@ func TestValidateMultiClusterServiceSpec(t *testing.T) {
Types: []networkingv1alpha1.ExposureType{
"",
},
Range: networkingv1alpha1.ExposureRange{
ClusterNames: []string{"member1"},
},
ServiceProvisionClusters: []string{"member1", "member2"},
ServiceConsumptionClusters: []string{"member1", "member2"},
},
},
expectedErr: field.ErrorList{field.Invalid(specFld.Child("types").Index(0), networkingv1alpha1.ExposureType(""), "ExposureType Error")},
Expand All @@ -138,12 +134,11 @@ func TestValidateMultiClusterServiceSpec(t *testing.T) {
Types: []networkingv1alpha1.ExposureType{
networkingv1alpha1.ExposureTypeCrossCluster,
},
Range: networkingv1alpha1.ExposureRange{
ClusterNames: []string{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
},
ServiceProvisionClusters: []string{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
ServiceConsumptionClusters: []string{},
},
},
expectedErr: field.ErrorList{field.Invalid(specFld.Child("range").Child("clusterNames").Index(0), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "must be no more than 48 characters")},
expectedErr: field.ErrorList{field.Invalid(specFld.Child("range").Child("serverLocaltions").Index(0), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "must be no more than 48 characters")},
},
}
for _, tt := range tests {
Expand Down

0 comments on commit 23abfd4

Please sign in to comment.