github.com/coreos/rocket@v1.30.1-0.20200224141603-171c416fac02/common/networking/ports.go (about) 1 // Copyright 2016 The rkt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package networking 16 17 import ( 18 "fmt" 19 "net" 20 21 "github.com/appc/spec/schema" 22 "github.com/appc/spec/schema/types" 23 ) 24 25 // ForwardedPort describes a port that will be 26 // forwarded (mapped) from the host to the pod 27 type ForwardedPort struct { 28 PodPort types.Port 29 HostPort types.ExposedPort 30 } 31 32 // findAppPort looks through the manifest to find a port with a given name. 33 // If multiple apps expose the same port name, it will fail 34 func findAppPort(manifest *schema.PodManifest, portName types.ACName) (*types.Port, error) { 35 var foundPort *types.Port 36 37 for _, app := range manifest.Apps { 38 for _, port := range app.App.Ports { 39 if portName == port.Name { 40 if foundPort != nil { // error: ambiguous 41 return nil, fmt.Errorf("port name %q defined multiple apps", portName) 42 } 43 p := port // duplicate b/c port gets overwritten 44 foundPort = &p 45 } 46 } 47 } 48 return foundPort, nil 49 } 50 51 // ForwardedPorts matches up ExposedPorts (host ports) with Ports on the app side. 52 // By default, it tries to match up by name - apps expose ports, and the podspec 53 // maps them. The podspec can also map from host to pod, without a corresponding app 54 // (which is needed for CRI) 55 // This will error if: 56 // - a name is ambiguous 57 // - the same port:proto combination is forwarded 58 func ForwardedPorts(manifest *schema.PodManifest) ([]ForwardedPort, error) { 59 var fps []ForwardedPort 60 var err error 61 62 // For every ExposedPort, find its corresponding PodPort 63 for _, ep := range manifest.Ports { 64 podPort := ep.PodPort 65 66 // If there is no direct mapping, search for the port by name 67 if podPort == nil { 68 podPort, err = findAppPort(manifest, ep.Name) 69 if err != nil { 70 return nil, err 71 } 72 if podPort == nil { 73 return nil, fmt.Errorf("port name %q could not be found in any apps", ep.Name) 74 } 75 } 76 fp := ForwardedPort{ 77 HostPort: ep, 78 PodPort: *podPort, 79 } 80 fp.HostPort.PodPort = &fp.PodPort 81 if fp.HostPort.HostIP == nil { 82 fp.HostPort.HostIP = net.IPv4(0, 0, 0, 0) 83 } 84 85 // Check all already-existing ports for conflicts 86 for idx := range fps { 87 if fp.conflicts(&fps[idx]) { 88 return nil, fmt.Errorf("port %s-%s:%d already mapped to pod port %d", 89 fp.PodPort.Protocol, fp.HostPort.HostIP.String(), fp.HostPort.HostPort, fps[idx].PodPort.Port) 90 } 91 } 92 93 fps = append(fps, fp) 94 } 95 return fps, nil 96 } 97 98 // conflicts checks if two ports conflict with each other 99 func (fp *ForwardedPort) conflicts(fp1 *ForwardedPort) bool { 100 if fp.PodPort.Protocol != fp1.PodPort.Protocol { 101 return false 102 } 103 104 if fp.HostPort.HostPort != fp1.HostPort.HostPort { 105 return false 106 } 107 108 // If either port has the 0.0.0.0 address, they conflict 109 zeroAddr := net.IPv4(0, 0, 0, 0) 110 if fp.HostPort.HostIP.Equal(zeroAddr) || fp1.HostPort.HostIP.Equal(zeroAddr) { 111 return true 112 } 113 114 if fp.HostPort.HostIP.Equal(fp1.HostPort.HostIP) { 115 return true 116 } 117 118 return false 119 }