Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump to v3.2.0 #10552

Merged
merged 7 commits into from
Jun 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
- Fixed a bug where the remote Podman client's `podman build --iidfile` command could include extra output (in addition to just the image ID) in the image ID file written ([#10233](https://github.com/containers/podman/issues/10233)).
- Fixed a bug where the remote Podman client's `podman build` command did not preserve hardlinks when moving files into the container via `COPY` instructions ([#9893](https://github.com/containers/podman/issues/9893)).
- Fixed a bug where the `podman generate systemd --new` command could generate extra `--iidfile` arguments if the container was already created with one.
- Fixed a bug where the `podman generate systemd --new` command would generate unit files that did not include `RequiresMountsFor` lines ([#10493](https://github.com/containers/podman/issues/10493)).
- Fixed a bug where the `podman generate kube` command produced incorrect YAML for containers which bind-mounted both `/` and `/root` from the host system into the container ([#9764](https://github.com/containers/podman/issues/9764)).
- Fixed a bug where pods created by `podman play kube` from YAML that specified `ShareProcessNamespace` would only share the PID namespace (and not also the UTS, Network, and IPC namespaces) ([#9128](https://github.com/containers/podman/issues/9128)).
- Fixed a bug where the `podman network reload` command could generate spurious error messages when `iptables-nft` was in use.
Expand All @@ -58,6 +59,9 @@
- Fixed a bug where Podman could freeze when creating containers with a specific combination of volumes and working directory ([#10216](https://github.com/containers/podman/issues/10216)).
- Fixed a bug where rootless Podman containers restarted by restart policy (e.g. containers created with `--restart=always`) would lose networking after being restarted ([#8047](https://github.com/containers/podman/issues/8047)).
- Fixed a bug where the `podman cp` command could not copy files into containers created with the `--pid=host` flag ([#9985](https://github.com/containers/podman/issues/9985)).
- Fixed a bug where filters to the `podman events` command could not be specified twice (if a filter is specified more than once, it will match if any of the given values match - logical or) ([#10507](https://github.com/containers/podman/issues/10507)).
- Fixed a bug where Podman would include IPv6 nameservers in `resolv.conf` in containers without IPv6 connectivity ([#10158](https://github.com/containers/podman/issues/10158)).
- Fixed a bug where containers could not be created with static IP addresses when connecting to a network using the `macvlan` driver ([#10283](https://github.com/containers/podman/issues/10283)).

### API
- Fixed a bug where the Compat Create endpoint for Containers did not allow advanced network options to be set ([#10110](https://github.com/containers/podman/issues/10110)).
Expand All @@ -67,11 +71,12 @@
- Fixed a bug where the Compat Create endpoint for Volumes required that the user provide a name for the new volume ([#9803](https://github.com/containers/podman/issues/9803)).
- Fixed a bug where the Libpod Info handler would sometimes not return the correct path to the Podman API socket.
- Fixed a bug where the Compat Events handler used the wrong name for container exited events (`died` instead of `die`) ([#10168](https://github.com/containers/podman/issues/10168)).
- Fixed a bug where the Compat Push endpoint for Images could leak goroutines if the remote end closed the connection prematurely.

### Misc
- Updated Buildah to v1.21.0
- Updated the containers/common library to v0.38.4
- Updated the containers/storage library to v1.31.1
- Updated the containers/common library to v0.38.5
- Updated the containers/storage library to v1.31.3

## 3.1.2
### Bugfixes
Expand Down
10 changes: 10 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
- Changelog for v3.2.0 (2021-06-03):
* Final release notes updates for v3.2.0
* add ipv6 nameservers only when the container has ipv6 enabled
* Use request context instead of background
* [v.3.2] events: support disjunctive filters
* System tests: add :Z to volume mounts
* generate systemd: make mounts portable
* vendor containers/[email protected]
* vendor containers/[email protected]

- Changelog for v3.2.0-RC3 (2021-05-26):
* Update release notes for v3.2.0-RC3
* Fix race on podman start --all
Expand Down
2 changes: 1 addition & 1 deletion contrib/spec/podman.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Epoch: 99
%else
Epoch: 0
%endif
Version: 3.2.0
Version: 3.2.1
Release: #COMMITDATE#.git%{shortcommit0}%{?dist}
Summary: Manage Pods, Containers and Container Images
License: ASL 2.0
Expand Down
34 changes: 26 additions & 8 deletions libpod/container_internal_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -1666,17 +1666,16 @@ func (c *Container) generateResolvConf() (string, error) {
return "", err
}

// Ensure that the container's /etc/resolv.conf is compatible with its
// network configuration.
// TODO: set ipv6 enable bool more sanely
resolv, err := resolvconf.FilterResolvDNS(contents, true, c.config.CreateNetNS)
if err != nil {
return "", errors.Wrapf(err, "error parsing host resolv.conf")
}

ipv6 := false
// Check if CNI gave back and DNS servers for us to add in
cniResponse := c.state.NetworkStatus
for _, i := range cniResponse {
for _, ip := range i.IPs {
// Note: only using To16() does not work since it also returns a vaild ip for ipv4
if ip.Address.IP.To4() == nil && ip.Address.IP.To16() != nil {
ipv6 = true
}
}
if i.DNS.Nameservers != nil {
cniNameServers = append(cniNameServers, i.DNS.Nameservers...)
logrus.Debugf("adding nameserver(s) from cni response of '%q'", i.DNS.Nameservers)
Expand All @@ -1687,6 +1686,25 @@ func (c *Container) generateResolvConf() (string, error) {
}
}

if c.config.NetMode.IsSlirp4netns() {
ctrNetworkSlipOpts := []string{}
if c.config.NetworkOptions != nil {
ctrNetworkSlipOpts = append(ctrNetworkSlipOpts, c.config.NetworkOptions["slirp4netns"]...)
}
slirpOpts, err := parseSlirp4netnsNetworkOptions(c.runtime, ctrNetworkSlipOpts)
if err != nil {
return "", err
}
ipv6 = slirpOpts.enableIPv6
}

// Ensure that the container's /etc/resolv.conf is compatible with its
// network configuration.
resolv, err := resolvconf.FilterResolvDNS(contents, ipv6, c.config.CreateNetNS)
if err != nil {
return "", errors.Wrapf(err, "error parsing host resolv.conf")
}

dns := make([]net.IP, 0, len(c.runtime.config.Containers.DNSServers))
for _, i := range c.runtime.config.Containers.DNSServers {
result := net.ParseIP(i)
Expand Down
43 changes: 18 additions & 25 deletions libpod/network/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,27 +44,27 @@ type CNIPlugins interface {
// HostLocalBridge describes a configuration for a bridge plugin
// https://github.com/containernetworking/plugins/tree/master/plugins/main/bridge#network-configuration-reference
type HostLocalBridge struct {
PluginType string `json:"type"`
BrName string `json:"bridge,omitempty"`
IsGW bool `json:"isGateway"`
IsDefaultGW bool `json:"isDefaultGateway,omitempty"`
ForceAddress bool `json:"forceAddress,omitempty"`
IPMasq bool `json:"ipMasq,omitempty"`
MTU int `json:"mtu,omitempty"`
HairpinMode bool `json:"hairpinMode,omitempty"`
PromiscMode bool `json:"promiscMode,omitempty"`
Vlan int `json:"vlan,omitempty"`
IPAM IPAMHostLocalConf `json:"ipam"`
PluginType string `json:"type"`
BrName string `json:"bridge,omitempty"`
IsGW bool `json:"isGateway"`
IsDefaultGW bool `json:"isDefaultGateway,omitempty"`
ForceAddress bool `json:"forceAddress,omitempty"`
IPMasq bool `json:"ipMasq,omitempty"`
MTU int `json:"mtu,omitempty"`
HairpinMode bool `json:"hairpinMode,omitempty"`
PromiscMode bool `json:"promiscMode,omitempty"`
Vlan int `json:"vlan,omitempty"`
IPAM IPAMConfig `json:"ipam"`
}

// Bytes outputs []byte
func (h *HostLocalBridge) Bytes() ([]byte, error) {
return json.MarshalIndent(h, "", "\t")
}

// IPAMHostLocalConf describes an IPAM configuration
// IPAMConfig describes an IPAM configuration
// https://github.com/containernetworking/plugins/tree/master/plugins/ipam/host-local#network-configuration-reference
type IPAMHostLocalConf struct {
type IPAMConfig struct {
PluginType string `json:"type"`
Routes []IPAMRoute `json:"routes,omitempty"`
ResolveConf string `json:"resolveConf,omitempty"`
Expand All @@ -81,7 +81,7 @@ type IPAMLocalHostRangeConf struct {
}

// Bytes outputs the configuration as []byte
func (i IPAMHostLocalConf) Bytes() ([]byte, error) {
func (i IPAMConfig) Bytes() ([]byte, error) {
return json.MarshalIndent(i, "", "\t")
}

Expand All @@ -101,19 +101,12 @@ func (p PortMapConfig) Bytes() ([]byte, error) {
return json.MarshalIndent(p, "", "\t")
}

// IPAMDHCP describes the ipamdhcp config
type IPAMDHCP struct {
DHCP string `json:"type"`
Routes []IPAMRoute `json:"routes,omitempty"`
Ranges [][]IPAMLocalHostRangeConf `json:"ranges,omitempty"`
}

// MacVLANConfig describes the macvlan config
type MacVLANConfig struct {
PluginType string `json:"type"`
Master string `json:"master"`
IPAM IPAMDHCP `json:"ipam"`
MTU int `json:"mtu,omitempty"`
PluginType string `json:"type"`
Master string `json:"master"`
IPAM IPAMConfig `json:"ipam"`
MTU int `json:"mtu,omitempty"`
}

// Bytes outputs the configuration as []byte
Expand Down
18 changes: 13 additions & 5 deletions libpod/network/netconflist.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func NewNcList(name, version string, labels NcLabels) NcList {
}

// NewHostLocalBridge creates a new LocalBridge for host-local
func NewHostLocalBridge(name string, isGateWay, isDefaultGW, ipMasq bool, mtu int, vlan int, ipamConf IPAMHostLocalConf) *HostLocalBridge {
func NewHostLocalBridge(name string, isGateWay, isDefaultGW, ipMasq bool, mtu int, vlan int, ipamConf IPAMConfig) *HostLocalBridge {
hostLocalBridge := HostLocalBridge{
PluginType: "bridge",
BrName: name,
Expand All @@ -65,8 +65,8 @@ func NewHostLocalBridge(name string, isGateWay, isDefaultGW, ipMasq bool, mtu in
}

// NewIPAMHostLocalConf creates a new IPAMHostLocal configuration
func NewIPAMHostLocalConf(routes []IPAMRoute, ipamRanges [][]IPAMLocalHostRangeConf) (IPAMHostLocalConf, error) {
ipamConf := IPAMHostLocalConf{
func NewIPAMHostLocalConf(routes []IPAMRoute, ipamRanges [][]IPAMLocalHostRangeConf) (IPAMConfig, error) {
ipamConf := IPAMConfig{
PluginType: "host-local",
Routes: routes,
// Possible future support ? Leaving for clues
Expand Down Expand Up @@ -177,15 +177,23 @@ func HasDNSNamePlugin(paths []string) bool {

// NewMacVLANPlugin creates a macvlanconfig with a given device name
func NewMacVLANPlugin(device string, gateway net.IP, ipRange *net.IPNet, subnet *net.IPNet, mtu int) (MacVLANConfig, error) {
i := IPAMDHCP{DHCP: "dhcp"}
if gateway != nil || ipRange != nil || subnet != nil {
i := IPAMConfig{PluginType: "dhcp"}
if gateway != nil ||
(ipRange != nil && ipRange.IP != nil && ipRange.Mask != nil) ||
(subnet != nil && subnet.IP != nil && subnet.Mask != nil) {
ipam, err := NewIPAMLocalHostRange(subnet, ipRange, gateway)
if err != nil {
return MacVLANConfig{}, err
}
ranges := make([][]IPAMLocalHostRangeConf, 0)
ranges = append(ranges, ipam)
i.Ranges = ranges
route, err := NewIPAMDefaultRoute(IsIPv6(subnet.IP))
if err != nil {
return MacVLANConfig{}, err
}
i.Routes = []IPAMRoute{route}
i.PluginType = "host-local"
}

m := MacVLANConfig{
Expand Down
112 changes: 52 additions & 60 deletions pkg/api/handlers/compat/images_push.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package compat

import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
Expand All @@ -12,7 +11,6 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
"github.com/containers/podman/v3/pkg/auth"
"github.com/containers/podman/v3/pkg/channel"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/containers/storage"
Expand Down Expand Up @@ -101,46 +99,33 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
destination = imageName
}

errorWriter := channel.NewWriter(make(chan []byte))
defer errorWriter.Close()

statusWriter := channel.NewWriter(make(chan []byte))
defer statusWriter.Close()

runCtx, cancel := context.WithCancel(context.Background())
var failed bool

go func() {
defer cancel()

statusWriter.Write([]byte(fmt.Sprintf("The push refers to repository [%s]", imageName)))

err := imageEngine.Push(runCtx, imageName, destination, options)
if err != nil {
if errors.Cause(err) != storage.ErrImageUnknown {
errorWriter.Write([]byte("An image does not exist locally with the tag: " + imageName))
} else {
errorWriter.Write([]byte(err.Error()))
}
}
}()

flush := func() {
if flusher, ok := w.(http.Flusher); ok {
flusher.Flush()
}
flush := func() {}
if flusher, ok := w.(http.Flusher); ok {
flush = flusher.Flush
}

w.WriteHeader(http.StatusOK)
w.Header().Add("Content-Type", "application/json")
flush()

var report jsonmessage.JSONMessage
enc := json.NewEncoder(w)
enc.SetEscapeHTML(true)

report.Status = fmt.Sprintf("The push refers to repository [%s]", imageName)
if err := enc.Encode(report); err != nil {
logrus.Warnf("Failed to json encode error %q", err.Error())
}
flush()

pushErrChan := make(chan error)
go func() {
pushErrChan <- imageEngine.Push(r.Context(), imageName, destination, options)
}()

loop: // break out of for/select infinite loop
for {
var report jsonmessage.JSONMessage
report = jsonmessage.JSONMessage{}

select {
case e := <-options.Progress:
Expand All @@ -160,43 +145,50 @@ loop: // break out of for/select infinite loop
}
report.ID = e.Artifact.Digest.Encoded()[0:12]
if err := enc.Encode(report); err != nil {
errorWriter.Write([]byte(err.Error()))
logrus.Warnf("Failed to json encode error %q", err.Error())
}
flush()
case e := <-statusWriter.Chan():
report.Status = string(e)
if err := enc.Encode(report); err != nil {
errorWriter.Write([]byte(err.Error()))
case err := <-pushErrChan:
if err != nil {
var msg string
if errors.Cause(err) != storage.ErrImageUnknown {
msg = "An image does not exist locally with the tag: " + imageName
} else {
msg = err.Error()
}
report.Error = &jsonmessage.JSONError{
Message: msg,
}
report.ErrorMessage = msg
if err := enc.Encode(report); err != nil {
logrus.Warnf("Failed to json encode error %q", err.Error())
}
flush()
break loop
}
flush()
case e := <-errorWriter.Chan():
failed = true
report.Error = &jsonmessage.JSONError{
Message: string(e),

digestBytes, err := ioutil.ReadAll(digestFile)
if err != nil {
report.Error = &jsonmessage.JSONError{
Message: err.Error(),
}
report.ErrorMessage = err.Error()
if err := enc.Encode(report); err != nil {
logrus.Warnf("Failed to json encode error %q", err.Error())
}
flush()
break loop
}
report.ErrorMessage = string(e)
tag := query.Tag
if tag == "" {
tag = "latest"
}
report.Status = fmt.Sprintf("%s: digest: %s", tag, string(digestBytes))
if err := enc.Encode(report); err != nil {
logrus.Warnf("Failed to json encode error %q", err.Error())
}

flush()
case <-runCtx.Done():
if !failed {
digestBytes, err := ioutil.ReadAll(digestFile)
if err == nil {
tag := query.Tag
if tag == "" {
tag = "latest"
}
report.Status = fmt.Sprintf("%s: digest: %s", tag, string(digestBytes))
if err := enc.Encode(report); err != nil {
logrus.Warnf("Failed to json encode error %q", err.Error())
}
flush()
}
}
break loop // break out of for/select infinite loop
case <-r.Context().Done():
// Client has closed connection
break loop // break out of for/select infinite loop
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/apiv2/01-basic.at
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ for i in /version version; do
t GET $i 200 \
.Components[0].Name="Podman Engine" \
.Components[0].Details.APIVersion~3[0-9.-]\\+ \
.Components[0].Details.MinAPIVersion=3.1.0 \
.Components[0].Details.MinAPIVersion=3.2.0 \
.Components[0].Details.Os=linux \
.ApiVersion=1.40 \
.MinAPIVersion=1.24 \
Expand Down
Loading