Merge pull request #17068 from ygalblum/quadlet-kube-publish-ports

Quadlet Kube - add support for PublishPort key
This commit is contained in:
OpenShift Merge Robot
2023-01-12 07:12:05 -05:00
committed by GitHub
7 changed files with 186 additions and 80 deletions

View File

@ -365,6 +365,23 @@ it may be absolute or relative to the location of the unit file.
This key may be used multiple times
#### `PublishPort=`
Exposes a port, or a range of ports (e.g. `50-59`), from the container to the host. Equivalent
to the `podman kube play`'s `--publish` option. The format is similar to the Podman options, which is of
the form `ip:hostPort:containerPort`, `ip::containerPort`, `hostPort:containerPort` or
`containerPort`, where the number of host and container ports must be the same (in the case
of a range).
If the IP is set to 0.0.0.0 or not set at all, the port will be bound on all IPv4 addresses on
the host; use [::] for IPv6.
The list of published ports specified in the unit file will be merged with the list of ports specified
in the Kubernetes YAML file. If the same container port and protocol is specified in both, the
entry from the unit file will take precedence
This key can be listed multiple times.
### Volume units
Volume files are named with a `.volume` extension and contain a section `[Volume]` describing the

View File

@ -141,6 +141,7 @@ var (
KeyRemapUIDSize: true,
KeyNetwork: true,
KeyConfigMap: true,
KeyPublishPort: true,
}
)
@ -454,63 +455,8 @@ func ConvertContainer(container *parser.UnitFile, isUser bool) (*parser.UnitFile
podman.addf("--expose=%s", exposedPort)
}
publishPorts := container.LookupAll(ContainerGroup, KeyPublishPort)
for _, publishPort := range publishPorts {
publishPort = strings.TrimSpace(publishPort) // Allow whitespace after
// IP address could have colons in it. For example: "[::]:8080:80/tcp, so use custom splitter
parts := splitPorts(publishPort)
var containerPort string
ip := ""
hostPort := ""
// format (from podman run):
// ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort
//
// ip could be IPv6 with minimum of these chars "[::]"
// containerPort can have a suffix of "/tcp" or "/udp"
//
switch len(parts) {
case 1:
containerPort = parts[0]
case 2:
hostPort = parts[0]
containerPort = parts[1]
case 3:
ip = parts[0]
hostPort = parts[1]
containerPort = parts[2]
default:
return nil, fmt.Errorf("invalid published port '%s'", publishPort)
}
if ip == "0.0.0.0" {
ip = ""
}
if len(hostPort) > 0 && !isPortRange(hostPort) {
return nil, fmt.Errorf("invalid port format '%s'", hostPort)
}
if len(containerPort) > 0 && !isPortRange(containerPort) {
return nil, fmt.Errorf("invalid port format '%s'", containerPort)
}
switch {
case len(ip) > 0 && len(hostPort) > 0:
podman.addf("-p=%s:%s:%s", ip, hostPort, containerPort)
case len(ip) > 0:
podman.addf("-p=%s::%s", ip, containerPort)
case len(hostPort) > 0:
podman.addf("-p=%s:%s", hostPort, containerPort)
default:
podman.addf("-p=%s", containerPort)
}
if err := handlePublishPorts(container, ContainerGroup, podman); err != nil {
return nil, err
}
podman.addEnv(podmanEnv)
@ -775,6 +721,10 @@ func ConvertKube(kube *parser.UnitFile, isUser bool) (*parser.UnitFile, error) {
execStart.add("--configmap", configMapPath)
}
if err := handlePublishPorts(kube, KubeGroup, execStart); err != nil {
return nil, err
}
execStart.add(yamlPath)
service.AddCmdline(ServiceGroup, "ExecStart", execStart.Args)
@ -876,3 +826,67 @@ func getAbsolutePath(quadletUnitFile *parser.UnitFile, filePath string) (string,
}
return filePath, nil
}
func handlePublishPorts(unitFile *parser.UnitFile, groupName string, podman *PodmanCmdline) error {
publishPorts := unitFile.LookupAll(groupName, KeyPublishPort)
for _, publishPort := range publishPorts {
publishPort = strings.TrimSpace(publishPort) // Allow whitespace after
// IP address could have colons in it. For example: "[::]:8080:80/tcp, so use custom splitter
parts := splitPorts(publishPort)
var containerPort string
ip := ""
hostPort := ""
// format (from podman run):
// ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort
//
// ip could be IPv6 with minimum of these chars "[::]"
// containerPort can have a suffix of "/tcp" or "/udp"
//
switch len(parts) {
case 1:
containerPort = parts[0]
case 2:
hostPort = parts[0]
containerPort = parts[1]
case 3:
ip = parts[0]
hostPort = parts[1]
containerPort = parts[2]
default:
return fmt.Errorf("invalid published port '%s'", publishPort)
}
if ip == "0.0.0.0" {
ip = ""
}
if len(hostPort) > 0 && !isPortRange(hostPort) {
return fmt.Errorf("invalid port format '%s'", hostPort)
}
if len(containerPort) > 0 && !isPortRange(containerPort) {
return fmt.Errorf("invalid port format '%s'", containerPort)
}
podman.add("--publish")
switch {
case len(ip) > 0 && len(hostPort) > 0:
podman.addf("%s:%s:%s", ip, hostPort, containerPort)
case len(ip) > 0:
podman.addf("%s::%s", ip, containerPort)
case len(hostPort) > 0:
podman.addf("%s:%s", hostPort, containerPort)
default:
podman.addf("%s", containerPort)
}
}
return nil
}

View File

@ -5,46 +5,46 @@ ExposeHostPort=1000
## assert-podman-args --expose=2000-3000
ExposeHostPort=2000-3000
## assert-podman-args -p=127.0.0.1:80:90
## assert-podman-args --publish 127.0.0.1:80:90
PublishPort=127.0.0.1:80:90
## assert-podman-args -p=80:91
## assert-podman-args --publish 80:91
PublishPort=0.0.0.0:80:91
## assert-podman-args -p=80:92
## assert-podman-args --publish 80:92
PublishPort=:80:92
## assert-podman-args -p=127.0.0.1::93
## assert-podman-args --publish 127.0.0.1::93
PublishPort=127.0.0.1::93
## assert-podman-args -p=94
## assert-podman-args --publish 94
PublishPort=0.0.0.0::94
## assert-podman-args -p=95
## assert-podman-args --publish 95
PublishPort=::95
## assert-podman-args -p=80:96
## assert-podman-args --publish 80:96
PublishPort=80:96
## assert-podman-args -p=97
## assert-podman-args --publish 97
PublishPort=97
## assert-podman-args -p=1234/udp
## assert-podman-args --publish 1234/udp
PublishPort=1234/udp
## assert-podman-args -p=1234:1234/udp
## assert-podman-args --publish 1234:1234/udp
PublishPort=1234:1234/udp
## assert-podman-args -p=127.0.0.1:1234:1234/udp
## assert-podman-args --publish 127.0.0.1:1234:1234/udp
PublishPort=127.0.0.1:1234:1234/udp
## assert-podman-args -p=1234/tcp
## assert-podman-args --publish 1234/tcp
PublishPort=1234/tcp
## assert-podman-args -p=1234:1234/tcp
## assert-podman-args --publish 1234:1234/tcp
PublishPort=1234:1234/tcp
## assert-podman-args -p=127.0.0.1:1234:1234/tcp
## assert-podman-args --publish 127.0.0.1:1234:1234/tcp
PublishPort=127.0.0.1:1234:1234/tcp
## assert-podman-args --expose=2000-3000/udp

View File

@ -0,0 +1,44 @@
[Kube]
Yaml=/opt/k8s/deployment.yml
## assert-podman-args --publish 127.0.0.1:80:90
PublishPort=127.0.0.1:80:90
## assert-podman-args --publish 80:91
PublishPort=0.0.0.0:80:91
## assert-podman-args --publish 80:92
PublishPort=:80:92
## assert-podman-args --publish 127.0.0.1::93
PublishPort=127.0.0.1::93
## assert-podman-args --publish 94
PublishPort=0.0.0.0::94
## assert-podman-args --publish 95
PublishPort=::95
## assert-podman-args --publish 80:96
PublishPort=80:96
## assert-podman-args --publish 97
PublishPort=97
## assert-podman-args --publish 1234/udp
PublishPort=1234/udp
## assert-podman-args --publish 1234:1234/udp
PublishPort=1234:1234/udp
## assert-podman-args --publish 127.0.0.1:1234:1234/udp
PublishPort=127.0.0.1:1234:1234/udp
## assert-podman-args --publish 1234/tcp
PublishPort=1234/tcp
## assert-podman-args --publish 1234:1234/tcp
PublishPort=1234:1234/tcp
## assert-podman-args --publish 127.0.0.1:1234:1234/tcp
PublishPort=127.0.0.1:1234:1234/tcp

View File

@ -1,28 +1,28 @@
[Container]
Image=localhost/imagename
## assert-podman-args -p=[::1]:80:90
## assert-podman-args --publish [::1]:80:90
PublishPort=[::1]:80:90
## assert-podman-args -p=[::]:80:91
## assert-podman-args --publish [::]:80:91
PublishPort=[::]:80:91
## assert-podman-args -p=[2001:DB8::23]:80:91
## assert-podman-args --publish [2001:DB8::23]:80:91
PublishPort=[2001:DB8::23]:80:91
## assert-podman-args -p=[::1]::93
## assert-podman-args --publish [::1]::93
PublishPort=[::1]::93
## assert-podman-args -p=[::]::94
## assert-podman-args --publish [::]::94
PublishPort=[::]::94
## assert-podman-args -p=[2001:db8::42]::94
## assert-podman-args --publish [2001:db8::42]::94
PublishPort=[2001:db8::42]::94
## assert-podman-args -p=[::1]:1234:1234/udp
## assert-podman-args --publish [::1]:1234:1234/udp
PublishPort=[::1]:1234:1234/udp
## assert-podman-args -p=[::1]:1234:1234/tcp
## assert-podman-args --publish [::1]:1234:1234/tcp
PublishPort=[::1]:1234:1234/tcp
## assert-podman-args -p=[2001:db8:c0:ff:ee::1]:1234:1234/udp
## assert-podman-args --publish [2001:db8:c0:ff:ee::1]:1234:1234/udp
PublishPort=[2001:db8:c0:ff:ee::1]:1234:1234/udp

View File

@ -0,0 +1,29 @@
[Kube]
Yaml=/opt/k8s/deployment.yml
## assert-podman-args --publish [::1]:80:90
PublishPort=[::1]:80:90
## assert-podman-args --publish [::]:80:91
PublishPort=[::]:80:91
## assert-podman-args --publish [2001:DB8::23]:80:91
PublishPort=[2001:DB8::23]:80:91
## assert-podman-args --publish [::1]::93
PublishPort=[::1]::93
## assert-podman-args --publish [::]::94
PublishPort=[::]::94
## assert-podman-args --publish [2001:db8::42]::94
PublishPort=[2001:db8::42]::94
## assert-podman-args --publish [::1]:1234:1234/udp
PublishPort=[::1]:1234:1234/udp
## assert-podman-args --publish [::1]:1234:1234/tcp
PublishPort=[::1]:1234:1234/tcp
## assert-podman-args --publish [2001:db8:c0:ff:ee::1]:1234:1234/udp
PublishPort=[2001:db8:c0:ff:ee::1]:1234:1234/udp

View File

@ -492,6 +492,8 @@ var _ = Describe("quadlet system generator", func() {
Entry("Kube - Network", "network.kube"),
Entry("Kube - Quadlet Network", "network.quadlet.kube"),
Entry("Kube - ConfigMap", "configmap.kube"),
Entry("Kube - Publish IPv4 ports", "ports.kube"),
Entry("Kube - Publish IPv6 ports", "ports_ipv6.kube"),
Entry("Network - Basic", "basic.network"),
Entry("Network - Label", "label.network"),