diff --git a/Makefile b/Makefile index cc173f1a04..e42e453215 100644 --- a/Makefile +++ b/Makefile @@ -830,7 +830,7 @@ install.remote: install.bin: install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(BINDIR) install ${SELINUXOPT} -m 755 bin/podman $(DESTDIR)$(BINDIR)/podman - ln -sfr $(DESTDIR)$(BINDIR)/podman $(DESTDIR)$(BINDIR)/podmansh + ln -sf podman $(DESTDIR)$(BINDIR)/podmansh test -z "${SELINUXOPT}" || chcon --verbose --reference=$(DESTDIR)$(BINDIR)/podman bin/podman install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(LIBEXECPODMAN) ifneq ($(shell uname -s),FreeBSD) diff --git a/cmd/podman/images/search.go b/cmd/podman/images/search.go index f88f8df042..1aea22d80e 100644 --- a/cmd/podman/images/search.go +++ b/cmd/podman/images/search.go @@ -182,7 +182,11 @@ func imageSearch(cmd *cobra.Command, args []string) error { listTagsEntries := buildListTagsJSON(searchReport) return printArbitraryJSON(listTagsEntries) } - rpt, err = rpt.Parse(report.OriginPodman, "{{range .}}{{.Name}}\t{{.Tag}}\n{{end -}}") + if cmd.Flags().Changed("format") { + rpt, err = rpt.Parse(report.OriginUser, searchOptions.Format) + } else { + rpt, err = rpt.Parse(report.OriginPodman, "{{range .}}{{.Name}}\t{{.Tag}}\n{{end -}}") + } case isJSON: return printArbitraryJSON(searchReport) case cmd.Flags().Changed("format"): diff --git a/cmd/podman/registry/registry.go b/cmd/podman/registry/registry.go index 207709ee24..c643a320f5 100644 --- a/cmd/podman/registry/registry.go +++ b/cmd/podman/registry/registry.go @@ -12,9 +12,6 @@ import ( "github.com/spf13/cobra" ) -// DefaultRootAPIPath is the default path of the REST socket -const DefaultRootAPIPath = "/run/podman/podman.sock" - // DefaultRootAPIAddress is the default address of the REST socket with unix: prefix const DefaultRootAPIAddress = "unix:" + DefaultRootAPIPath diff --git a/cmd/podman/registry/registry_common.go b/cmd/podman/registry/registry_common.go new file mode 100644 index 0000000000..2b0cdb16f9 --- /dev/null +++ b/cmd/podman/registry/registry_common.go @@ -0,0 +1,7 @@ +//go:build !freebsd +// +build !freebsd + +package registry + +// DefaultRootAPIPath is the default path of the REST socket +const DefaultRootAPIPath = "/run/podman/podman.sock" diff --git a/cmd/podman/registry/registry_freebsd.go b/cmd/podman/registry/registry_freebsd.go new file mode 100644 index 0000000000..3529681a94 --- /dev/null +++ b/cmd/podman/registry/registry_freebsd.go @@ -0,0 +1,4 @@ +package registry + +// DefaultRootAPIPath is the default path of the REST socket +const DefaultRootAPIPath = "/var/run/podman/podman.sock" diff --git a/cmd/podman/system/service.go b/cmd/podman/system/service.go index bb8156d4c5..53572234a8 100644 --- a/cmd/podman/system/service.go +++ b/cmd/podman/system/service.go @@ -1,5 +1,6 @@ -//go:build linux && !remote -// +build linux,!remote +//go:build (linux || freebsd) && !remote +// +build linux freebsd +// +build !remote package system diff --git a/cmd/podman/system/service_abi.go b/cmd/podman/system/service_abi.go index 5c57a5df2c..f5ae6fd509 100644 --- a/cmd/podman/system/service_abi.go +++ b/cmd/podman/system/service_abi.go @@ -1,5 +1,6 @@ -//go:build linux && !remote -// +build linux,!remote +//go:build (linux || freebsd) && !remote +// +build linux freebsd +// +build !remote package system @@ -12,7 +13,6 @@ import ( "path/filepath" "github.com/containers/common/pkg/cgroups" - "github.com/containers/common/pkg/servicereaper" "github.com/containers/podman/v4/cmd/podman/registry" api "github.com/containers/podman/v4/pkg/api/server" "github.com/containers/podman/v4/pkg/domain/entities" @@ -119,7 +119,7 @@ func restService(flags *pflag.FlagSet, cfg *entities.PodmanConfig, opts entities logrus.Debugf("Could not move to subcgroup: %v", err) } - servicereaper.Start() + maybeStartServiceReaper() infra.StartWatcher(libpodRuntime) server, err := api.NewServerWithSettings(libpodRuntime, listener, opts) if err != nil { diff --git a/cmd/podman/system/service_abi_common.go b/cmd/podman/system/service_abi_common.go new file mode 100644 index 0000000000..999f90fbe9 --- /dev/null +++ b/cmd/podman/system/service_abi_common.go @@ -0,0 +1,7 @@ +//go:build !linux && !remote + +package system + +// Currently, we only need servicereaper on Linux to support slirp4netns. +func maybeStartServiceReaper() { +} diff --git a/cmd/podman/system/service_abi_linux.go b/cmd/podman/system/service_abi_linux.go new file mode 100644 index 0000000000..d0da1594ad --- /dev/null +++ b/cmd/podman/system/service_abi_linux.go @@ -0,0 +1,12 @@ +//go:build linux && !remote + +package system + +import ( + "github.com/containers/common/pkg/servicereaper" +) + +// Currently, we only need servicereaper on Linux to support slirp4netns. +func maybeStartServiceReaper() { + servicereaper.Start() +} diff --git a/libpod/container_internal_common.go b/libpod/container_internal_common.go index a389abe4eb..7dfceac8a6 100644 --- a/libpod/container_internal_common.go +++ b/libpod/container_internal_common.go @@ -2203,6 +2203,12 @@ func (c *Container) getHostsEntries() (etchosts.HostEntries, error) { switch { case c.config.NetMode.IsBridge(): entries = etchosts.GetNetworkHostEntries(c.state.NetworkStatus, names...) + case c.config.NetMode.IsPasta(): + ip, err := getPastaIP(c.state) + if err != nil { + return nil, err + } + entries = etchosts.HostEntries{{IP: ip.String(), Names: names}} case c.config.NetMode.IsSlirp4netns(): ip, err := getSlirp4netnsIP(c.slirp4netnsSubnet) if err != nil { diff --git a/libpod/networking_freebsd.go b/libpod/networking_freebsd.go index aa0f9bbb3a..ab2d4557de 100644 --- a/libpod/networking_freebsd.go +++ b/libpod/networking_freebsd.go @@ -271,3 +271,7 @@ func (c *Container) reloadRootlessRLKPortMapping() error { func (c *Container) setupRootlessNetwork() error { return nil } + +func getPastaIP(state *ContainerState) (net.IP, error) { + return nil, fmt.Errorf("pasta networking is Linux only") +} diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 8e45759153..b8485a2844 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -19,6 +19,7 @@ import ( "github.com/containers/common/libnetwork/resolvconf" "github.com/containers/common/libnetwork/slirp4netns" "github.com/containers/common/libnetwork/types" + netUtil "github.com/containers/common/libnetwork/util" "github.com/containers/common/pkg/netns" "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/pkg/rootless" @@ -757,3 +758,13 @@ func (c *Container) inspectJoinedNetworkNS(networkns string) (q types.StatusBloc }) return result, err } + +func getPastaIP(state *ContainerState) (net.IP, error) { + var ip string + err := ns.WithNetNSPath(state.NetNS, func(_ ns.NetNS) error { + // get the first ip in the netns + ip = netUtil.GetLocalIP() + return nil + }) + return net.ParseIP(ip), err +} diff --git a/pkg/api/handlers/compat/containers_stats_freebsd.go b/pkg/api/handlers/compat/containers_stats_freebsd.go new file mode 100644 index 0000000000..5745547691 --- /dev/null +++ b/pkg/api/handlers/compat/containers_stats_freebsd.go @@ -0,0 +1,15 @@ +package compat + +import ( + "fmt" + "net/http" + "time" + + "github.com/containers/podman/v4/pkg/api/handlers/utils" +) + +const DefaultStatsPeriod = 5 * time.Second + +func StatsContainer(w http.ResponseWriter, r *http.Request) { + utils.Error(w, http.StatusBadRequest, fmt.Errorf("compat.StatsContainer not supported on FreeBSD")) +} diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats_linux.go similarity index 100% rename from pkg/api/handlers/compat/containers_stats.go rename to pkg/api/handlers/compat/containers_stats_linux.go diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go index bc5a90b912..4d2f8c303e 100644 --- a/pkg/domain/infra/abi/system.go +++ b/pkg/domain/infra/abi/system.go @@ -35,7 +35,7 @@ func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) { // we are reporting the default systemd activation socket path as we cannot know if a future // service may be run with another URI. if ic.Libpod.RemoteURI() == "" { - xdg := "/run" + xdg := defaultRunPath if path, err := util.GetRuntimeDir(); err != nil { // Info is as good as we can guess... return info, err diff --git a/pkg/domain/infra/abi/system_freebsd.go b/pkg/domain/infra/abi/system_freebsd.go new file mode 100644 index 0000000000..33ccebbb37 --- /dev/null +++ b/pkg/domain/infra/abi/system_freebsd.go @@ -0,0 +1,4 @@ +package abi + +// Default path for system runtime state +const defaultRunPath = "/var/run" diff --git a/pkg/domain/infra/abi/system_linux.go b/pkg/domain/infra/abi/system_linux.go new file mode 100644 index 0000000000..6a13f07050 --- /dev/null +++ b/pkg/domain/infra/abi/system_linux.go @@ -0,0 +1,4 @@ +package abi + +// Default path for system runtime state +const defaultRunPath = "/run" diff --git a/pkg/machine/hyperv/machine.go b/pkg/machine/hyperv/machine.go index d0473663e4..acaf0fb863 100644 --- a/pkg/machine/hyperv/machine.go +++ b/pkg/machine/hyperv/machine.go @@ -186,6 +186,7 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) { // VSOCK-CONNECT:2 <- shortcut to connect to the hostvm ready := `[Unit] After=remove-moby.service sshd.socket sshd.service +After=systemd-user-sessions.service OnFailure=emergency.target OnFailureJobMode=isolate [Service] diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 390d23f078..fb792cc425 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -398,6 +398,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { ready := `[Unit] Requires=dev-virtio\\x2dports-%s.device After=remove-moby.service sshd.socket sshd.service +After=systemd-user-sessions.service OnFailure=emergency.target OnFailureJobMode=isolate [Service] diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 3f47c6b4cf..e20746aeba 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -197,7 +197,7 @@ func GetKeepIDMapping(opts *namespaces.KeepIDUserNsOptions) (*stypes.IDMappingOp if err != nil { return nil, 0, 0, err } - gids, err := rootless.ReadMappingsProc("/proc/self/uid_map") + gids, err := rootless.ReadMappingsProc("/proc/self/gid_map") if err != nil { return nil, 0, 0, err } diff --git a/test/e2e/search_test.go b/test/e2e/search_test.go index 3760951d96..0d4e18335f 100644 --- a/test/e2e/search_test.go +++ b/test/e2e/search_test.go @@ -177,6 +177,13 @@ registries = ['{{.Host}}:{{.Port}}']` } }) + It("podman search format list tags with custom", func() { + search := podmanTest.Podman([]string{"search", "--list-tags", "--format", "{{.Name}}", "--limit", "1", ALPINE}) + search.WaitWithDefaultTimeout() + Expect(search).Should(Exit(0)) + Expect(search.OutputToString()).To(Equal("quay.io/libpod/alpine")) + }) + It("podman search attempts HTTP if tls-verify flag is set false", func() { if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") diff --git a/test/system/505-networking-pasta.bats b/test/system/505-networking-pasta.bats index d5b1890641..c55b7d3eb9 100644 --- a/test/system/505-networking-pasta.bats +++ b/test/system/505-networking-pasta.bats @@ -18,6 +18,21 @@ function setup() { XFER_FILE="${PODMAN_TMPDIR}/pasta.bin" } +function default_ifname() { + local ip_ver="${1}" + + local expr='[.[] | select(.dst == "default").dev] | .[0]' + ip -j -"${ip_ver}" route show | jq -rM "${expr}" +} + +function default_addr() { + local ip_ver="${1}" + local ifname="${2:-$(default_ifname "${ip_ver}")}" + + local expr='.[0] | .addr_info[0].local' + ip -j -"${ip_ver}" addr show "${ifname}" | jq -rM "${expr}" +} + # pasta_test_do() - Run tests involving clients and servers # $1: IP version: 4 or 6 # $2: Interface type: "tap" or "loopback" @@ -38,29 +53,20 @@ function pasta_test_do() { # Calculate and set addresses, if [ ${ip_ver} -eq 4 ]; then skip_if_no_ipv4 "IPv4 not routable on the host" - if [ ${iftype} = "loopback" ]; then - local addr="127.0.0.1" - else - local addr="$(ipv4_get_addr_global)" - fi elif [ ${ip_ver} -eq 6 ]; then skip_if_no_ipv6 "IPv6 not routable on the host" - if [ ${iftype} = "loopback" ]; then - local addr="::1" - else - local addr="$(ipv6_get_addr_global)" - fi else skip "Unsupported IP version" fi - # interface names, if [ ${iftype} = "loopback" ]; then local ifname="lo" else - local ifname="$(ether_get_name)" + local ifname="$(default_ifname "${ip_ver}")" fi + local addr="$(default_addr "${ip_ver}" "${ifname}")" + # ports, if [ ${range} -gt 1 ]; then local port="$(random_free_port_range ${range} ${addr} ${proto})" @@ -168,7 +174,7 @@ function teardown() { run_podman run --net=pasta $IMAGE ip -j -4 address show local container_address="$(ipv4_get_addr_global "${output}")" - local host_address="$(ipv4_get_addr_global)" + local host_address="$(default_addr 4)" assert "${container_address}" = "${host_address}" \ "Container address not matching host" @@ -203,7 +209,7 @@ function teardown() { run_podman run --net=pasta $IMAGE ip -j -6 address show local container_address="$(ipv6_get_addr_global "${output}")" - local host_address="$(ipv6_get_addr_global)" + local host_address="$(default_addr 6)" assert "${container_address}" = "${host_address}" \ "Container address not matching host" @@ -232,6 +238,21 @@ function teardown() { "Container has IPv6 global address with IPv6 disabled" } +@test "podman networking with pasta(1) - podman puts pasta IP in /etc/hosts" { + skip_if_no_ipv4 "IPv4 not routable on the host" + + pname="p$(random_string 30)" + ip="$(default_addr 4)" + + run_podman pod create --net=pasta --name "${pname}" + run_podman run --pod="${pname}" "${IMAGE}" getent hosts "${pname}" + + assert "$(echo ${output} | cut -f1 -d' ')" = "${ip}" "Correct /etc/hsots entry missing" + + run_podman pod rm "${pname}" + run_podman rmi $(pause_image) +} + ### Routes ##################################################################### @test "podman networking with pasta(1) - IPv4 default route" {