Compare container ports in a smarter way (#1755)
* Compare ports ingoring order and considering protocol defaults Co-authored-by: Felix Kunde <felix-kunde@gmx.de>
This commit is contained in:
		
							parent
							
								
									d8a159ef1a
								
							
						
					
					
						commit
						fb8a6c7a68
					
				|  | @ -523,7 +523,7 @@ func (c *Cluster) compareContainers(description string, setA, setB []v1.Containe | ||||||
| 		newCheck("new statefulset %s's %s (index %d) name does not match the current one", | 		newCheck("new statefulset %s's %s (index %d) name does not match the current one", | ||||||
| 			func(a, b v1.Container) bool { return a.Name != b.Name }), | 			func(a, b v1.Container) bool { return a.Name != b.Name }), | ||||||
| 		newCheck("new statefulset %s's %s (index %d) ports do not match the current one", | 		newCheck("new statefulset %s's %s (index %d) ports do not match the current one", | ||||||
| 			func(a, b v1.Container) bool { return !reflect.DeepEqual(a.Ports, b.Ports) }), | 			func(a, b v1.Container) bool { return !comparePorts(a.Ports, b.Ports) }), | ||||||
| 		newCheck("new statefulset %s's %s (index %d) resources do not match the current ones", | 		newCheck("new statefulset %s's %s (index %d) resources do not match the current ones", | ||||||
| 			func(a, b v1.Container) bool { return !compareResources(&a.Resources, &b.Resources) }), | 			func(a, b v1.Container) bool { return !compareResources(&a.Resources, &b.Resources) }), | ||||||
| 		newCheck("new statefulset %s's %s (index %d) environment does not match the current one", | 		newCheck("new statefulset %s's %s (index %d) environment does not match the current one", | ||||||
|  | @ -634,6 +634,46 @@ func compareSpiloConfiguration(configa, configb string) bool { | ||||||
| 	return reflect.DeepEqual(oa, ob) | 	return reflect.DeepEqual(oa, ob) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func areProtocolsEqual(a, b v1.Protocol) bool { | ||||||
|  | 	return a == b || | ||||||
|  | 		(a == "" && b == v1.ProtocolTCP) || | ||||||
|  | 		(a == v1.ProtocolTCP && b == "") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func comparePorts(a, b []v1.ContainerPort) bool { | ||||||
|  | 	if len(a) != len(b) { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	areContainerPortsEqual := func(a, b v1.ContainerPort) bool { | ||||||
|  | 		return a.Name == b.Name && | ||||||
|  | 			a.HostPort == b.HostPort && | ||||||
|  | 			areProtocolsEqual(a.Protocol, b.Protocol) && | ||||||
|  | 			a.HostIP == b.HostIP | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	findByPortValue := func(portSpecs []v1.ContainerPort, port int32) (v1.ContainerPort, bool) { | ||||||
|  | 		for _, portSpec := range portSpecs { | ||||||
|  | 			if portSpec.ContainerPort == port { | ||||||
|  | 				return portSpec, true | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return v1.ContainerPort{}, false | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, portA := range a { | ||||||
|  | 		portB, found := findByPortValue(b, portA.ContainerPort) | ||||||
|  | 		if !found { | ||||||
|  | 			return false | ||||||
|  | 		} | ||||||
|  | 		if !areContainerPortsEqual(portA, portB) { | ||||||
|  | 			return false | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return true | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (c *Cluster) enforceMinResourceLimits(spec *acidv1.PostgresSpec) error { | func (c *Cluster) enforceMinResourceLimits(spec *acidv1.PostgresSpec) error { | ||||||
| 
 | 
 | ||||||
| 	var ( | 	var ( | ||||||
|  |  | ||||||
|  | @ -5,6 +5,8 @@ import ( | ||||||
| 	"reflect" | 	"reflect" | ||||||
| 	"testing" | 	"testing" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 
 | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
| 	acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" | 	acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" | ||||||
| 	fakeacidv1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/fake" | 	fakeacidv1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/fake" | ||||||
|  | @ -1088,3 +1090,102 @@ func TestValidUsernames(t *testing.T) { | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func TestComparePorts(t *testing.T) { | ||||||
|  | 	testCases := []struct { | ||||||
|  | 		name     string | ||||||
|  | 		setA     []v1.ContainerPort | ||||||
|  | 		setB     []v1.ContainerPort | ||||||
|  | 		expected bool | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name: "different ports", | ||||||
|  | 			setA: []v1.ContainerPort{ | ||||||
|  | 				{ | ||||||
|  | 					Name:          "metrics", | ||||||
|  | 					ContainerPort: 9187, | ||||||
|  | 					Protocol:      v1.ProtocolTCP, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 
 | ||||||
|  | 			setB: []v1.ContainerPort{ | ||||||
|  | 				{ | ||||||
|  | 					Name:          "http", | ||||||
|  | 					ContainerPort: 80, | ||||||
|  | 					Protocol:      v1.ProtocolTCP, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			expected: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "no difference", | ||||||
|  | 			setA: []v1.ContainerPort{ | ||||||
|  | 				{ | ||||||
|  | 					Name:          "metrics", | ||||||
|  | 					ContainerPort: 9187, | ||||||
|  | 					Protocol:      v1.ProtocolTCP, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			setB: []v1.ContainerPort{ | ||||||
|  | 				{ | ||||||
|  | 					Name:          "metrics", | ||||||
|  | 					ContainerPort: 9187, | ||||||
|  | 					Protocol:      v1.ProtocolTCP, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			expected: true, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "same ports, different order", | ||||||
|  | 			setA: []v1.ContainerPort{ | ||||||
|  | 				{ | ||||||
|  | 					Name:          "metrics", | ||||||
|  | 					ContainerPort: 9187, | ||||||
|  | 					Protocol:      v1.ProtocolTCP, | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					Name:          "http", | ||||||
|  | 					ContainerPort: 80, | ||||||
|  | 					Protocol:      v1.ProtocolTCP, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			setB: []v1.ContainerPort{ | ||||||
|  | 				{ | ||||||
|  | 					Name:          "http", | ||||||
|  | 					ContainerPort: 80, | ||||||
|  | 					Protocol:      v1.ProtocolTCP, | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					Name:          "metrics", | ||||||
|  | 					ContainerPort: 9187, | ||||||
|  | 					Protocol:      v1.ProtocolTCP, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			expected: true, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "same ports, but one with default protocol", | ||||||
|  | 			setA: []v1.ContainerPort{ | ||||||
|  | 				{ | ||||||
|  | 					Name:          "metrics", | ||||||
|  | 					ContainerPort: 9187, | ||||||
|  | 					Protocol:      v1.ProtocolTCP, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			setB: []v1.ContainerPort{ | ||||||
|  | 				{ | ||||||
|  | 					Name:          "metrics", | ||||||
|  | 					ContainerPort: 9187, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			expected: true, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, testCase := range testCases { | ||||||
|  | 		t.Run(testCase.name, func(t *testing.T) { | ||||||
|  | 			got := comparePorts(testCase.setA, testCase.setB) | ||||||
|  | 			assert.Equal(t, testCase.expected, got) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue