Skip to content

Commit

Permalink
cherry pick pingcap#2610 to release-1.1
Browse files Browse the repository at this point in the history
Signed-off-by: sre-bot <sre-bot@pingcap.com>
  • Loading branch information
shonge authored and sre-bot committed Jun 8, 2020
1 parent 07e664b commit 3f4e61c
Show file tree
Hide file tree
Showing 11 changed files with 456 additions and 3 deletions.
17 changes: 17 additions & 0 deletions docs/api-references/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -8038,6 +8038,23 @@ string
<p>PortName is the name of service port</p>
</td>
</tr>
<tr>
<td>
<code>loadBalancerSourceRanges</code></br>
<em>
[]string
</em>
</td>
<td>
<em>(Optional)</em>
<p>LoadBalancerSourceRanges is the loadBalancerSourceRanges of service
If specified and supported by the platform, this will restrict traffic through the cloud-provider
load-balancer will be restricted to the specified client IPs. This field will be ignored if the
cloud-provider does not support the feature.&rdquo;
More info: <a href="https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/">https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/</a>
Optional: Defaults to omitted</p>
</td>
</tr>
</tbody>
</table>
<h3 id="status">Status</h3>
Expand Down
4 changes: 4 additions & 0 deletions manifests/crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,10 @@ spec:
type: string
loadBalancerIP:
type: string
loadBalancerSourceRanges:
items:
type: string
type: array
portName:
type: string
type:
Expand Down
14 changes: 14 additions & 0 deletions pkg/apis/pingcap/v1alpha1/openapi_generated.go

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

9 changes: 9 additions & 0 deletions pkg/apis/pingcap/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,15 @@ type ServiceSpec struct {
// PortName is the name of service port
// +optional
PortName *string `json:"portName,omitempty"`

// LoadBalancerSourceRanges is the loadBalancerSourceRanges of service
// If specified and supported by the platform, this will restrict traffic through the cloud-provider
// load-balancer will be restricted to the specified client IPs. This field will be ignored if the
// cloud-provider does not support the feature."
// More info: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/
// Optional: Defaults to omitted
// +optional
LoadBalancerSourceRanges []string `json:"loadBalancerSourceRanges,omitempty"`
}

// +k8s:openapi-gen=true
Expand Down
29 changes: 28 additions & 1 deletion pkg/apis/pingcap/v1alpha1/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ import (
"github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1"
"github.com/pingcap/tidb-operator/pkg/label"
corev1 "k8s.io/api/core/v1"

apivalidation "k8s.io/apimachinery/pkg/api/validation"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
utilnet "k8s.io/utils/net"
)

// ValidateTidbCluster validates a TidbCluster, it performs basic validation for all TidbClusters despite it is legacy
Expand All @@ -42,6 +42,17 @@ func ValidateTidbCluster(tc *v1alpha1.TidbCluster) field.ErrorList {
return allErrs
}

func ValidateTidbMonitor(monitor *v1alpha1.TidbMonitor) field.ErrorList {
allErrs := field.ErrorList{}
// validate monitor service
if monitor.Spec.Grafana != nil {
allErrs = append(allErrs, validateService(&monitor.Spec.Grafana.Service, field.NewPath("spec"))...)
}
allErrs = append(allErrs, validateService(&monitor.Spec.Prometheus.Service, field.NewPath("spec"))...)
allErrs = append(allErrs, validateService(&monitor.Spec.Reloader.Service, field.NewPath("spec"))...)
return allErrs
}

func validateAnnotations(anns map[string]string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateAnnotations(anns, fldPath)...)
Expand Down Expand Up @@ -164,6 +175,9 @@ func validateTiFlashConfig(config *v1alpha1.TiFlashConfig, path *field.Path) fie
func validateTiDBSpec(spec *v1alpha1.TiDBSpec, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, validateComponentSpec(&spec.ComponentSpec, fldPath)...)
if spec.Service != nil {
allErrs = append(allErrs, validateService(&spec.Service.ServiceSpec, fldPath)...)
}
return allErrs
}

Expand Down Expand Up @@ -399,3 +413,16 @@ func validateDeleteSlots(annotations map[string]string, key string, fldPath *fie
}
return allErrs
}

func validateService(spec *v1alpha1.ServiceSpec, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
//validate LoadBalancerSourceRanges field from service
if len(spec.LoadBalancerSourceRanges) > 0 {
ip := spec.LoadBalancerSourceRanges
_, err := utilnet.ParseIPNets(ip...)
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("spec.LoadBalancerSourceRanges"), spec.LoadBalancerSourceRanges, "service.Spec.LoadBalancerSourceRanges is not valid. Expecting a list of IP ranges. For example, 10.0.0.0/24."))
}
}
return allErrs
}
86 changes: 86 additions & 0 deletions pkg/apis/pingcap/v1alpha1/validation/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,95 @@ func TestValidateRequestsStorage(t *testing.T) {
}
}

func TestValidateService(t *testing.T) {
g := NewGomegaWithT(t)
tests := []struct {
name string
loadBalancerSourceRanges []string
expectedErrors int
}{
{
name: "correct LoadBalancerSourceRanges",
loadBalancerSourceRanges: strings.Split("192.168.0.1/32", ","),
expectedErrors: 0,
},
{
name: "incorrect LoadBalancerSourceRanges",
loadBalancerSourceRanges: strings.Split("192.168.0.1", ","),
expectedErrors: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
svc := newService()
svc.LoadBalancerSourceRanges = tt.loadBalancerSourceRanges
err := validateService(svc, field.NewPath("spec"))
r := len(err)
g.Expect(r).Should(Equal(tt.expectedErrors))
if r > 0 {
for _, e := range err {
g.Expect(e.Detail).To(ContainSubstring("service.Spec.LoadBalancerSourceRanges is not valid. Expecting a list of IP ranges. For example, 10.0.0.0/24."))
}
}
})
}
}

func TestValidateTidbMonitor(t *testing.T) {
g := NewGomegaWithT(t)
tests := []struct {
name string
loadBalancerSourceRanges []string
expectedErrors int
}{
{
name: "correct LoadBalancerSourceRanges",
loadBalancerSourceRanges: strings.Split("192.168.0.1/24,192.168.1.1/24", ","),
expectedErrors: 0,
},
{
name: "incorrect LoadBalancerSourceRanges",
loadBalancerSourceRanges: strings.Split("192.168.0.1,192.168.1.1", ","),
expectedErrors: 3,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
monitor := newTidbMonitor()
monitor.Spec.Prometheus.Service.LoadBalancerSourceRanges = tt.loadBalancerSourceRanges
monitor.Spec.Grafana.Service.LoadBalancerSourceRanges = tt.loadBalancerSourceRanges
monitor.Spec.Reloader.Service.LoadBalancerSourceRanges = tt.loadBalancerSourceRanges
err := ValidateTidbMonitor(monitor)
r := len(err)
g.Expect(r).Should(Equal(tt.expectedErrors))
if r > 0 {
for _, e := range err {
g.Expect(e.Detail).To(ContainSubstring("service.Spec.LoadBalancerSourceRanges is not valid. Expecting a list of IP ranges. For example, 10.0.0.0/24."))
}
}
})
}
}

func newTidbCluster() *v1alpha1.TidbCluster {
tc := &v1alpha1.TidbCluster{}
tc.Name = "test-validate-requests-storage"
tc.Namespace = "default"
return tc
}

func newService() *v1alpha1.ServiceSpec {
svc := &v1alpha1.ServiceSpec{}
return svc
}

func newTidbMonitor() *v1alpha1.TidbMonitor {
monitor := &v1alpha1.TidbMonitor{
Spec: v1alpha1.TidbMonitorSpec{
Grafana: &v1alpha1.GrafanaSpec{},
Prometheus: v1alpha1.PrometheusSpec{},
Reloader: v1alpha1.ReloaderSpec{},
},
}
return monitor
}
5 changes: 5 additions & 0 deletions pkg/apis/pingcap/v1alpha1/zz_generated.deepcopy.go

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

9 changes: 7 additions & 2 deletions pkg/manager/member/tidb_member_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,8 +473,13 @@ func getNewTiDBServiceOrNil(tc *v1alpha1.TidbCluster) *corev1.Service {
Selector: tidbLabels,
},
}
if svcSpec.LoadBalancerIP != nil {
tidbSvc.Spec.LoadBalancerIP = *svcSpec.LoadBalancerIP
if svcSpec.Type == corev1.ServiceTypeLoadBalancer {
if svcSpec.LoadBalancerIP != nil {
tidbSvc.Spec.LoadBalancerIP = *svcSpec.LoadBalancerIP
}
if svcSpec.LoadBalancerSourceRanges != nil {
tidbSvc.Spec.LoadBalancerSourceRanges = svcSpec.LoadBalancerSourceRanges
}
}
if svcSpec.ExternalTrafficPolicy != nil {
tidbSvc.Spec.ExternalTrafficPolicy = *svcSpec.ExternalTrafficPolicy
Expand Down
9 changes: 9 additions & 0 deletions pkg/manager/member/tidb_member_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1347,6 +1347,10 @@ func TestTiDBInitContainers(t *testing.T) {
func TestGetNewTiDBService(t *testing.T) {
g := NewGomegaWithT(t)
trafficPolicy := corev1.ServiceExternalTrafficPolicyTypeLocal
loadBalancerSourceRanges := []string{
"10.0.0.0/8",
"130.211.204.1/32",
}
testCases := []struct {
name string
tc v1alpha1.TidbCluster
Expand Down Expand Up @@ -1499,6 +1503,7 @@ func TestGetNewTiDBService(t *testing.T) {
Annotations: map[string]string{
"lb-type": "testlb",
},
LoadBalancerSourceRanges: loadBalancerSourceRanges,
},
ExternalTrafficPolicy: &trafficPolicy,
ExposeStatus: pointer.BoolPtr(true),
Expand Down Expand Up @@ -1537,6 +1542,10 @@ func TestGetNewTiDBService(t *testing.T) {
Spec: corev1.ServiceSpec{
Type: corev1.ServiceTypeLoadBalancer,
ExternalTrafficPolicy: corev1.ServiceExternalTrafficPolicyTypeLocal,
LoadBalancerSourceRanges: []string{
"10.0.0.0/8",
"130.211.204.1/32",
},
Ports: []corev1.ServicePort{
{
Name: "mysql-client",
Expand Down
9 changes: 9 additions & 0 deletions pkg/monitor/monitor/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,9 @@ func getMonitorService(monitor *v1alpha1.TidbMonitor) []*core.Service {
if monitor.Spec.Prometheus.Service.LoadBalancerIP != nil {
prometheusService.Spec.LoadBalancerIP = *monitor.Spec.Prometheus.Service.LoadBalancerIP
}
if monitor.Spec.Prometheus.Service.LoadBalancerSourceRanges != nil {
prometheusService.Spec.LoadBalancerSourceRanges = monitor.Spec.Prometheus.Service.LoadBalancerSourceRanges
}
}

reloaderService := &core.Service{
Expand Down Expand Up @@ -718,6 +721,9 @@ func getMonitorService(monitor *v1alpha1.TidbMonitor) []*core.Service {
if monitor.Spec.Reloader.Service.LoadBalancerIP != nil {
reloaderService.Spec.LoadBalancerIP = *monitor.Spec.Reloader.Service.LoadBalancerIP
}
if monitor.Spec.Reloader.Service.LoadBalancerSourceRanges != nil {
reloaderService.Spec.LoadBalancerSourceRanges = monitor.Spec.Reloader.Service.LoadBalancerSourceRanges
}
}

services = append(services, prometheusService, reloaderService)
Expand Down Expand Up @@ -748,6 +754,9 @@ func getMonitorService(monitor *v1alpha1.TidbMonitor) []*core.Service {
if monitor.Spec.Grafana.Service.LoadBalancerIP != nil {
grafanaService.Spec.LoadBalancerIP = *monitor.Spec.Grafana.Service.LoadBalancerIP
}
if monitor.Spec.Grafana.Service.LoadBalancerSourceRanges != nil {
grafanaService.Spec.LoadBalancerSourceRanges = monitor.Spec.Grafana.Service.LoadBalancerSourceRanges
}
}

services = append(services, grafanaService)
Expand Down
Loading

0 comments on commit 3f4e61c

Please sign in to comment.