@@ -38,6 +38,51 @@ type portSpace struct {
3838 dynamicPortSpace * idm.Idm
3939}
4040
41+ type allocatedPorts map [api.PortConfig ]map [uint32 ]* api.PortConfig
42+
43+ func (ps allocatedPorts ) addState (p * api.PortConfig ) {
44+ portKey := getPortConfigKey (p )
45+ if _ , ok := ps [portKey ]; ! ok {
46+ ps [portKey ] = make (map [uint32 ]* api.PortConfig )
47+ }
48+ ps [portKey ][p.PublishedPort ] = p
49+ }
50+
51+ func (ps allocatedPorts ) delState (p * api.PortConfig ) * api.PortConfig {
52+ portKey := getPortConfigKey (p )
53+
54+ portStateMap , ok := ps [portKey ]
55+
56+ // If name, port, protocol values don't match then we
57+ // are not allocated.
58+ if ! ok {
59+ return nil
60+ }
61+
62+ if p .PublishedPort != 0 {
63+ // If SwarmPort was user defined but the port state
64+ // SwarmPort doesn't match we are not allocated.
65+ v := portStateMap [p .PublishedPort ]
66+
67+ // Delete state from allocatedPorts
68+ delete (portStateMap , p .PublishedPort )
69+
70+ return v
71+ }
72+
73+ // If PublishedPort == 0 and we don't have non-zero port
74+ // then we are not allocated
75+ for publishedPort , v := range portStateMap {
76+ if publishedPort != 0 {
77+ // Delete state from allocatedPorts
78+ delete (portStateMap , publishedPort )
79+ return v
80+ }
81+ }
82+
83+ return nil
84+ }
85+
4186func newPortAllocator () (* portAllocator , error ) {
4287 portSpaces := make (map [api.PortConfig_Protocol ]* portSpace )
4388 for _ , protocol := range []api.PortConfig_Protocol {api .ProtocolTCP , api .ProtocolUDP } {
@@ -91,40 +136,54 @@ func reconcilePortConfigs(s *api.Service) []*api.PortConfig {
91136 return s .Spec .Endpoint .Ports
92137 }
93138
94- allocatedPorts := make ( map [api. PortConfig ] * api. PortConfig )
139+ portStates := allocatedPorts {}
95140 for _ , portState := range s .Endpoint .Ports {
96- if portState .PublishMode ! = api .PublishModeIngress {
97- continue
141+ if portState .PublishMode = = api .PublishModeIngress {
142+ portStates . addState ( portState )
98143 }
99-
100- allocatedPorts [getPortConfigKey (portState )] = portState
101144 }
102145
103146 var portConfigs []* api.PortConfig
147+
148+ // Process the portConfig with portConfig.PublishMode != api.PublishModeIngress
149+ // and PublishedPort != 0 (high priority)
104150 for _ , portConfig := range s .Spec .Endpoint .Ports {
105151 // If the PublishMode is not Ingress simply pick up
106152 // the port config.
107153 if portConfig .PublishMode != api .PublishModeIngress {
108154 portConfigs = append (portConfigs , portConfig )
109155 continue
110156 }
157+ if portConfig .PublishedPort != 0 {
158+ // Remove record from portState
159+ portStates .delState (portConfig )
111160
112- portState , ok := allocatedPorts [getPortConfigKey (portConfig )]
161+ // For PublishedPort != 0 prefer the portConfig
162+ portConfigs = append (portConfigs , portConfig )
163+ }
164+ }
165+
166+ // Iterate portConfigs with PublishedPort == 0 (low priority)
167+ for _ , portConfig := range s .Spec .Endpoint .Ports {
168+ // Ignore ports which are not PublishModeIngress (already processed)
169+ if portConfig .PublishMode != api .PublishModeIngress {
170+ continue
171+ }
113172
114173 // If the portConfig is exactly the same as portState
115174 // except if SwarmPort is not user-define then prefer
116175 // portState to ensure sticky allocation of the same
117176 // port that was allocated before.
118- if ok && portConfig .Name == portState .Name &&
119- portConfig .TargetPort == portState .TargetPort &&
120- portConfig .Protocol == portState .Protocol &&
121- portConfig .PublishedPort == 0 {
122- portConfigs = append (portConfigs , portState )
123- continue
124- }
177+ if portConfig .PublishedPort == 0 {
178+ // Remove record from portState
179+ if portState := portStates .delState (portConfig ); portState != nil {
180+ portConfigs = append (portConfigs , portState )
181+ continue
182+ }
125183
126- // For all other cases prefer the portConfig
127- portConfigs = append (portConfigs , portConfig )
184+ // For all other cases prefer the portConfig
185+ portConfigs = append (portConfigs , portConfig )
186+ }
128187 }
129188
130189 return portConfigs
@@ -213,40 +272,31 @@ func (pa *portAllocator) isPortsAllocated(s *api.Service) bool {
213272 return false
214273 }
215274
216- allocatedPorts := make ( map [api. PortConfig ] * api. PortConfig )
275+ portStates := allocatedPorts {}
217276 for _ , portState := range s .Endpoint .Ports {
218- if portState .PublishMode ! = api .PublishModeIngress {
219- continue
277+ if portState .PublishMode = = api .PublishModeIngress {
278+ portStates . addState ( portState )
220279 }
221-
222- allocatedPorts [getPortConfigKey (portState )] = portState
223280 }
224281
282+ // Iterate portConfigs with PublishedPort != 0 (high priority)
225283 for _ , portConfig := range s .Spec .Endpoint .Ports {
226284 // Ignore ports which are not PublishModeIngress
227285 if portConfig .PublishMode != api .PublishModeIngress {
228286 continue
229287 }
230-
231- portState , ok := allocatedPorts [getPortConfigKey (portConfig )]
232-
233- // If name, port, protocol values don't match then we
234- // are not allocated.
235- if ! ok {
288+ if portConfig .PublishedPort != 0 && portStates .delState (portConfig ) == nil {
236289 return false
237290 }
291+ }
238292
239- // If SwarmPort was user defined but the port state
240- // SwarmPort doesn't match we are not allocated.
241- if portConfig . PublishedPort != portState . PublishedPort &&
242- portConfig .PublishedPort != 0 {
243- return false
293+ // Iterate portConfigs with PublishedPort == 0 (low priority)
294+ for _ , portConfig := range s . Spec . Endpoint . Ports {
295+ // Ignore ports which are not PublishModeIngress
296+ if portConfig .PublishMode != api . PublishModeIngress {
297+ continue
244298 }
245-
246- // If SwarmPort was not defined by user and port state
247- // is not initialized with a valid SwarmPort value then
248- // we are not allocated.
249- if portConfig .PublishedPort == 0 && portState .PublishedPort == 0 {
299+ if portConfig .PublishedPort == 0 && portStates .delState (portConfig ) == nil {
250300 return false
251301 }
252302 }
0 commit comments