summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2021-11-19 10:01:02 +0100
committerMiloslav Trmač <mitr@redhat.com>2021-11-30 22:13:52 +0100
commitf415b3055290b383c76d98127ec168ddea629680 (patch)
treeb43793cbf686389fc6c079e03b6b0486cd769baf
parenta948ecbb9c7c90e249cded94a2239192a4ad766a (diff)
downloadpodman-f415b3055290b383c76d98127ec168ddea629680.tar.gz
podman-f415b3055290b383c76d98127ec168ddea629680.tar.bz2
podman-f415b3055290b383c76d98127ec168ddea629680.zip
Ensure the generated NodePort values are unique
... at least within a single service. [NO NEW TESTS NEEDED] because testing RNGs is problematic. (We _could_ probably inject a mock RNG implementation that always returns the same value, or something like that.) Signed-off-by: Miloslav Trmač <mitr@redhat.com>
-rw-r--r--libpod/kube.go22
1 files changed, 18 insertions, 4 deletions
diff --git a/libpod/kube.go b/libpod/kube.go
index bdd5b9a4f..4e61b5377 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -277,12 +277,14 @@ func GenerateKubeServiceFromV1Pod(pod *v1.Pod, servicePorts []v1.ServicePort) (Y
type servicePortState struct {
// A program using the shared math/rand state with the default seed will produce the same sequence of pseudo-random numbers
// for each execution. Use a private RNG state not to interfere with other users.
- rng *rand.Rand
+ rng *rand.Rand
+ usedPorts map[int]struct{}
}
func newServicePortState() servicePortState {
return servicePortState{
- rng: rand.New(rand.NewSource(time.Now().UnixNano())),
+ rng: rand.New(rand.NewSource(time.Now().UnixNano())),
+ usedPorts: map[int]struct{}{},
}
}
@@ -291,8 +293,20 @@ func newServicePortState() servicePortState {
func (state *servicePortState) containerPortsToServicePorts(containerPorts []v1.ContainerPort) ([]v1.ServicePort, error) {
sps := make([]v1.ServicePort, 0, len(containerPorts))
for _, cp := range containerPorts {
- // Legal nodeport range is 30000-32767
- nodePort := 30000 + state.rng.Intn(32767-30000+1)
+ var nodePort int
+ attempt := 0
+ for {
+ // Legal nodeport range is 30000-32767
+ nodePort = 30000 + state.rng.Intn(32767-30000+1)
+ if _, found := state.usedPorts[nodePort]; !found {
+ state.usedPorts[nodePort] = struct{}{}
+ break
+ }
+ attempt++
+ if attempt >= 100 {
+ return nil, fmt.Errorf("too many attempts trying to generate a unique NodePort number")
+ }
+ }
servicePort := v1.ServicePort{
Protocol: cp.Protocol,
Port: cp.ContainerPort,