aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common/completion.go4
-rw-r--r--cmd/podman/containers/port.go2
-rw-r--r--cmd/podman/containers/rename.go7
-rw-r--r--docs/source/markdown/links/podman-container-rename.11
-rw-r--r--pkg/bindings/README.md156
-rw-r--r--pkg/bindings/containers/rename.go28
-rw-r--r--pkg/bindings/containers/types.go7
-rw-r--r--pkg/bindings/containers/types_rename_options.go104
-rw-r--r--pkg/bindings/images/build.go138
-rw-r--r--pkg/domain/infra/tunnel/containers.go2
-rw-r--r--pkg/specgen/generate/oci.go39
-rw-r--r--test/e2e/build_test.go216
-rw-r--r--test/e2e/pod_stats_test.go5
-rw-r--r--test/e2e/rename_test.go1
-rw-r--r--test/e2e/run_ns_test.go8
15 files changed, 664 insertions, 54 deletions
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go
index d01842998..c9a3c5e94 100644
--- a/cmd/podman/common/completion.go
+++ b/cmd/podman/common/completion.go
@@ -517,8 +517,8 @@ func AutocompleteRunlabelCommand(cmd *cobra.Command, args []string, toComplete s
return nil, cobra.ShellCompDirectiveDefault
}
-// AutocompletePortCommand - Autocomplete podman port command args.
-func AutocompletePortCommand(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+// AutocompleteContainerOneArg - Autocomplete containers as fist arg.
+func AutocompleteContainerOneArg(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
diff --git a/cmd/podman/containers/port.go b/cmd/podman/containers/port.go
index d59161149..4d3a5310d 100644
--- a/cmd/podman/containers/port.go
+++ b/cmd/podman/containers/port.go
@@ -26,7 +26,7 @@ var (
Args: func(cmd *cobra.Command, args []string) error {
return validate.CheckAllLatestAndCIDFile(cmd, args, true, false)
},
- ValidArgsFunction: common.AutocompletePortCommand,
+ ValidArgsFunction: common.AutocompleteContainerOneArg,
Example: `podman port --all
podman port ctrID 80/tcp
podman port --latest 80`,
diff --git a/cmd/podman/containers/rename.go b/cmd/podman/containers/rename.go
index 9c94e6272..78bd3db83 100644
--- a/cmd/podman/containers/rename.go
+++ b/cmd/podman/containers/rename.go
@@ -16,7 +16,7 @@ var (
Long: renameDescription,
RunE: rename,
Args: cobra.ExactArgs(2),
- ValidArgsFunction: common.AutocompletePortCommand,
+ ValidArgsFunction: common.AutocompleteContainerOneArg,
Example: "podman rename containerA newName",
}
@@ -32,14 +32,13 @@ var (
)
func init() {
- // TODO: Once bindings are done, add this to TunnelMode
registry.Commands = append(registry.Commands, registry.CliCommand{
- Mode: []entities.EngineMode{entities.ABIMode},
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: renameCommand,
})
registry.Commands = append(registry.Commands, registry.CliCommand{
- Mode: []entities.EngineMode{entities.ABIMode},
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: containerRenameCommand,
Parent: containerCmd,
})
diff --git a/docs/source/markdown/links/podman-container-rename.1 b/docs/source/markdown/links/podman-container-rename.1
new file mode 100644
index 000000000..1e71c57b6
--- /dev/null
+++ b/docs/source/markdown/links/podman-container-rename.1
@@ -0,0 +1 @@
+.so man1/podman-rename.1
diff --git a/pkg/bindings/README.md b/pkg/bindings/README.md
new file mode 100644
index 000000000..149deda5e
--- /dev/null
+++ b/pkg/bindings/README.md
@@ -0,0 +1,156 @@
+# Podman Golang bindings
+The Podman Go bindings are a set of functions to allow developers to execute Podman operations from within their Go based application. The Go bindings
+connect to a Podman service which can run locally or on a remote machine. You can perform many operations including pulling and listing images, starting,
+stopping or inspecting containers. Currently, the Podman repository has bindings available for operations on images, containers, pods,
+networks and manifests among others.
+
+## Quick Start
+The bindings require that the Podman system service is running for the specified user. This can be done with systemd using the `systemctl` command or manually
+by calling the service directly.
+
+### Starting the service with system
+The command to start the Podman service differs slightly depending on the user that is running the service. For a rootful service,
+start the service like this:
+```
+# systemctl start podman.socket
+```
+For a non-privileged, aka rootless, user, start the service like this:
+
+```
+$ systemctl start --user podman.socket
+```
+
+### Starting the service manually
+It can be handy to run the system service manually. Doing so allows you to enable debug messaging.
+```
+$ podman --log-level=debug system service -t0
+```
+If you do not provide a specific path for the socket, a default is provided. The location of that socket for
+rootful connections is `/run/podman/podman.sock` and for rootless it is `/run/USERID#/podman/podman.sock`. For more
+information about the Podman system service, see `man podman-system-service`.
+
+### Creating a connection
+The first step for using the bindings is to create a connection to the socket. As mentioned earlier, the destination
+of the socket depends on the user who owns it. In this case, a rootful connection is made.
+
+```
+import (
+ "context"
+ "fmt"
+ "os"
+
+ "github.com/containers/podman/v2/pkg/bindings"
+)
+
+func main() {
+ conn, err := bindings.NewConnection(context.Background(), "unix://run/podman/podman.sock")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+
+}
+```
+The `conn` variable returned from the `bindings.NewConnection` function can then be used in subsequent function calls
+to interact with containers.
+
+### Examples
+The following examples build upon the connection example from above. They are all rootful connections as well.
+
+#### Inspect a container
+The following example obtains the inspect information for a container named `foorbar` and then prints
+the container's ID. Note the use of optional inspect options for size.
+```
+import (
+ "context"
+ "fmt"
+ "os"
+
+ "github.com/containers/podman/v2/pkg/bindings"
+ "github.com/containers/podman/v2/pkg/bindings/containers"
+)
+
+func main() {
+ conn, err := bindings.NewConnection(context.Background(), "unix://run/podman/podman.sock")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ inspectData, err := containers.Inspect(conn, "foobar", new(containers.InspectOptions).WithSize(true))
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ // Print the container ID
+ fmt.Println(inspectData.ID)
+}
+```
+
+#### Pull an image
+The following example pulls the image `quay.ioo/libpod/alpine_nginx` to the local image store.
+```
+import (
+ "context"
+ "fmt"
+ "os"
+
+ "github.com/containers/podman/v2/pkg/bindings"
+ "github.com/containers/podman/v2/pkg/bindings/images"
+)
+
+func main() {
+ conn, err := bindings.NewConnection(context.Background(), "unix://run/podman/podman.sock")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ _, err = images.Pull(conn, "quay.io/libpod/alpine_nginx", nil)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+}
+
+```
+
+#### Pull an image, create a container, and start the container
+The following example pulls the `quay.io/libpod/alpine_nginx` image and then creates a container named `foobar`
+from it. And finally, it starts the container.
+```
+import (
+ "context"
+ "fmt"
+ "os"
+
+ "github.com/containers/podman/v2/pkg/bindings"
+ "github.com/containers/podman/v2/pkg/bindings/containers"
+ "github.com/containers/podman/v2/pkg/bindings/images"
+ "github.com/containers/podman/v2/pkg/specgen"
+)
+
+func main() {
+ conn, err := bindings.NewConnection(context.Background(), "unix://run/podman/podman.sock")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ _, err = images.Pull(conn, "quay.io/libpod/alpine_nginx", nil)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ s := specgen.NewSpecGenerator("quay.io/libpod/alpine_nginx", false)
+ s.Name = "foobar"
+ createResponse, err := containers.CreateWithSpec(conn, s, nil)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ fmt.Println("Container created.")
+ if err := containers.Start(conn, createResponse.ID, nil); err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ fmt.Println("Container started.")
+}
+```
diff --git a/pkg/bindings/containers/rename.go b/pkg/bindings/containers/rename.go
new file mode 100644
index 000000000..0e8c7f198
--- /dev/null
+++ b/pkg/bindings/containers/rename.go
@@ -0,0 +1,28 @@
+package containers
+
+import (
+ "context"
+ "net/http"
+
+ "github.com/containers/podman/v2/pkg/bindings"
+)
+
+// Rename an existing container.
+func Rename(ctx context.Context, nameOrID string, options *RenameOptions) error {
+ if options == nil {
+ options = new(RenameOptions)
+ }
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return err
+ }
+ params, err := options.ToParams()
+ if err != nil {
+ return err
+ }
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/rename", params, nil, nameOrID)
+ if err != nil {
+ return err
+ }
+ return response.Process(nil)
+}
diff --git a/pkg/bindings/containers/types.go b/pkg/bindings/containers/types.go
index 24402e982..10f553e52 100644
--- a/pkg/bindings/containers/types.go
+++ b/pkg/bindings/containers/types.go
@@ -194,6 +194,13 @@ type InitOptions struct{}
// ShouldRestartOptions
type ShouldRestartOptions struct{}
+//go:generate go run ../generator/generator.go RenameOptions
+// RenameOptions are options for renaming containers.
+// The Name field is required.
+type RenameOptions struct {
+ Name *string
+}
+
//go:generate go run ../generator/generator.go ResizeTTYOptions
// ResizeTTYOptions are optional options for resizing
// container TTYs
diff --git a/pkg/bindings/containers/types_rename_options.go b/pkg/bindings/containers/types_rename_options.go
new file mode 100644
index 000000000..b7a723f7a
--- /dev/null
+++ b/pkg/bindings/containers/types_rename_options.go
@@ -0,0 +1,104 @@
+package containers
+
+import (
+ "net/url"
+ "reflect"
+ "strconv"
+ "strings"
+
+ jsoniter "github.com/json-iterator/go"
+ "github.com/pkg/errors"
+)
+
+/*
+This file is generated automatically by go generate. Do not edit.
+*/
+
+// Changed
+func (o *RenameOptions) Changed(fieldName string) bool {
+ r := reflect.ValueOf(o)
+ value := reflect.Indirect(r).FieldByName(fieldName)
+ return !value.IsNil()
+}
+
+// ToParams
+func (o *RenameOptions) ToParams() (url.Values, error) {
+ params := url.Values{}
+ if o == nil {
+ return params, nil
+ }
+ json := jsoniter.ConfigCompatibleWithStandardLibrary
+ s := reflect.ValueOf(o)
+ if reflect.Ptr == s.Kind() {
+ s = s.Elem()
+ }
+ sType := s.Type()
+ for i := 0; i < s.NumField(); i++ {
+ fieldName := sType.Field(i).Name
+ if !o.Changed(fieldName) {
+ continue
+ }
+ fieldName = strings.ToLower(fieldName)
+ f := s.Field(i)
+ if reflect.Ptr == f.Kind() {
+ f = f.Elem()
+ }
+ switch f.Kind() {
+ case reflect.Bool:
+ params.Set(fieldName, strconv.FormatBool(f.Bool()))
+ case reflect.String:
+ params.Set(fieldName, f.String())
+ case reflect.Int, reflect.Int64:
+ // f.Int() is always an int64
+ params.Set(fieldName, strconv.FormatInt(f.Int(), 10))
+ case reflect.Uint, reflect.Uint64:
+ // f.Uint() is always an uint64
+ params.Set(fieldName, strconv.FormatUint(f.Uint(), 10))
+ case reflect.Slice:
+ typ := reflect.TypeOf(f.Interface()).Elem()
+ switch typ.Kind() {
+ case reflect.String:
+ sl := f.Slice(0, f.Len())
+ s, ok := sl.Interface().([]string)
+ if !ok {
+ return nil, errors.New("failed to convert to string slice")
+ }
+ for _, val := range s {
+ params.Add(fieldName, val)
+ }
+ default:
+ return nil, errors.Errorf("unknown slice type %s", f.Kind().String())
+ }
+ case reflect.Map:
+ lowerCaseKeys := make(map[string][]string)
+ iter := f.MapRange()
+ for iter.Next() {
+ lowerCaseKeys[iter.Key().Interface().(string)] = iter.Value().Interface().([]string)
+
+ }
+ s, err := json.MarshalToString(lowerCaseKeys)
+ if err != nil {
+ return nil, err
+ }
+
+ params.Set(fieldName, s)
+ }
+ }
+ return params, nil
+}
+
+// WithName
+func (o *RenameOptions) WithName(value string) *RenameOptions {
+ v := &value
+ o.Name = v
+ return o
+}
+
+// GetName
+func (o *RenameOptions) GetName() string {
+ var name string
+ if o.Name == nil {
+ return name
+ }
+ return *o.Name
+}
diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go
index d34ab87d9..02765816f 100644
--- a/pkg/bindings/images/build.go
+++ b/pkg/bindings/images/build.go
@@ -2,6 +2,7 @@ package images
import (
"archive/tar"
+ "compress/gzip"
"context"
"encoding/json"
"io"
@@ -18,6 +19,7 @@ import (
"github.com/containers/podman/v2/pkg/auth"
"github.com/containers/podman/v2/pkg/bindings"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/storage/pkg/fileutils"
"github.com/docker/go-units"
"github.com/hashicorp/go-multierror"
jsoniter "github.com/json-iterator/go"
@@ -138,12 +140,38 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
entries := make([]string, len(containerFiles))
copy(entries, containerFiles)
entries = append(entries, options.ContextDirectory)
- tarfile, err := nTar(entries...)
+
+ excludes := options.Excludes
+ if len(excludes) == 0 {
+ excludes, err = parseDockerignore(options.ContextDirectory)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ tarfile, err := nTar(excludes, entries...)
if err != nil {
+ logrus.Errorf("cannot tar container entries %v error: %v", entries, err)
return nil, err
}
defer tarfile.Close()
- params.Set("dockerfile", filepath.Base(containerFiles[0]))
+
+ containerFile, err := filepath.Abs(entries[0])
+ if err != nil {
+ logrus.Errorf("cannot find absolute path of %v: %v", entries[0], err)
+ return nil, err
+ }
+ contextDir, err := filepath.Abs(entries[1])
+ if err != nil {
+ logrus.Errorf("cannot find absolute path of %v: %v", entries[1], err)
+ return nil, err
+ }
+
+ if strings.HasPrefix(containerFile, contextDir+string(filepath.Separator)) {
+ containerFile = strings.TrimPrefix(containerFile, contextDir+string(filepath.Separator))
+ }
+
+ params.Set("dockerfile", containerFile)
conn, err := bindings.GetClient(ctx)
if err != nil {
@@ -200,52 +228,116 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
}
}
-func nTar(sources ...string) (io.ReadCloser, error) {
+func nTar(excludes []string, sources ...string) (io.ReadCloser, error) {
+ pm, err := fileutils.NewPatternMatcher(excludes)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error processing excludes list %v", excludes)
+ }
+
if len(sources) == 0 {
return nil, errors.New("No source(s) provided for build")
}
pr, pw := io.Pipe()
- tw := tar.NewWriter(pw)
+ gw := gzip.NewWriter(pw)
+ tw := tar.NewWriter(gw)
var merr error
go func() {
defer pw.Close()
+ defer gw.Close()
defer tw.Close()
for _, src := range sources {
- s := src
- err := filepath.Walk(s, func(path string, info os.FileInfo, err error) error {
+ s, err := filepath.Abs(src)
+ if err != nil {
+ logrus.Errorf("cannot stat one of source context: %v", err)
+ merr = multierror.Append(merr, err)
+ return
+ }
+
+ err = filepath.Walk(s, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
- if !info.Mode().IsRegular() || path == s {
- return nil
- }
- f, lerr := os.Open(path)
- if lerr != nil {
- return lerr
+ if path == s {
+ return nil // skip root dir
}
name := strings.TrimPrefix(path, s+string(filepath.Separator))
- hdr, lerr := tar.FileInfoHeader(info, name)
- if lerr != nil {
- f.Close()
- return lerr
+
+ excluded, err := pm.Matches(filepath.ToSlash(name)) // nolint:staticcheck
+ if err != nil {
+ return errors.Wrapf(err, "error checking if %q is excluded", name)
}
- hdr.Name = name
- if lerr := tw.WriteHeader(hdr); lerr != nil {
- f.Close()
- return lerr
+ if excluded {
+ return nil
}
- _, cerr := io.Copy(tw, f)
- f.Close()
- return cerr
+ if info.Mode().IsRegular() { // add file item
+ f, lerr := os.Open(path)
+ if lerr != nil {
+ return lerr
+ }
+
+ hdr, lerr := tar.FileInfoHeader(info, name)
+ if lerr != nil {
+ f.Close()
+ return lerr
+ }
+ hdr.Name = name
+ if lerr := tw.WriteHeader(hdr); lerr != nil {
+ f.Close()
+ return lerr
+ }
+
+ _, cerr := io.Copy(tw, f)
+ f.Close()
+ return cerr
+ } else if info.Mode().IsDir() { // add folders
+ hdr, lerr := tar.FileInfoHeader(info, name)
+ if lerr != nil {
+ return lerr
+ }
+ hdr.Name = name
+ if lerr := tw.WriteHeader(hdr); lerr != nil {
+ return lerr
+ }
+ } else if info.Mode()&os.ModeSymlink != 0 { // add symlinks as it, not content
+ link, err := os.Readlink(path)
+ if err != nil {
+ return err
+ }
+ hdr, lerr := tar.FileInfoHeader(info, link)
+ if lerr != nil {
+ return lerr
+ }
+ hdr.Name = name
+ if lerr := tw.WriteHeader(hdr); lerr != nil {
+ return lerr
+ }
+ } //skip other than file,folder and symlinks
+ return nil
})
merr = multierror.Append(merr, err)
}
}()
return pr, merr
}
+
+func parseDockerignore(root string) ([]string, error) {
+ ignore, err := ioutil.ReadFile(filepath.Join(root, ".dockerignore"))
+ if err != nil && !os.IsNotExist(err) {
+ return nil, errors.Wrapf(err, "error reading .dockerignore: '%s'", root)
+ }
+ rawexcludes := strings.Split(string(ignore), "\n")
+ excludes := make([]string, 0, len(rawexcludes))
+ for _, e := range rawexcludes {
+ if len(e) == 0 || e[0] == '#' {
+ continue
+ }
+ excludes = append(excludes, e)
+ }
+ return excludes, nil
+}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 8aab4a9cd..4ee623703 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -823,5 +823,5 @@ func (ic *ContainerEngine) ShouldRestart(_ context.Context, id string) (bool, er
// ContainerRename renames the given container.
func (ic *ContainerEngine) ContainerRename(ctx context.Context, nameOrID string, opts entities.ContainerRenameOptions) error {
- return errors.Errorf("NOT YET IMPLEMENTED")
+ return containers.Rename(ic.ClientCtx, nameOrID, new(containers.RenameOptions).WithName(opts.NewName))
}
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index 7dc32a314..e62131244 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -138,10 +138,23 @@ func makeCommand(ctx context.Context, s *specgen.SpecGenerator, img *image.Image
return finalCommand, nil
}
+// canMountSys is a best-effort heuristic to detect whether mounting a new sysfs is permitted in the container
+func canMountSys(isRootless, isNewUserns bool, s *specgen.SpecGenerator) bool {
+ if s.NetNS.IsHost() && (isRootless || isNewUserns) {
+ return false
+ }
+ if isNewUserns {
+ switch s.NetNS.NSMode {
+ case specgen.Slirp, specgen.Private, specgen.NoNetwork, specgen.Bridge:
+ return true
+ default:
+ return false
+ }
+ }
+ return true
+}
+
func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, rtc *config.Config, newImage *image.Image, mounts []spec.Mount, pod *libpod.Pod, finalCmd []string) (*spec.Spec, error) {
- var (
- inUserNS bool
- )
cgroupPerm := "ro"
g, err := generate.New("linux")
if err != nil {
@@ -151,23 +164,11 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
g.RemoveMount("/dev/shm")
g.HostSpecific = true
addCgroup := true
- canMountSys := true
isRootless := rootless.IsRootless()
- if isRootless {
- inUserNS = true
- }
- if !s.UserNS.IsHost() {
- if s.UserNS.IsContainer() || s.UserNS.IsPath() {
- inUserNS = true
- }
- if s.UserNS.IsPrivate() {
- inUserNS = true
- }
- }
- if inUserNS && s.NetNS.NSMode != specgen.NoNetwork {
- canMountSys = false
- }
+ isNewUserns := s.UserNS.IsContainer() || s.UserNS.IsPath() || s.UserNS.IsPrivate()
+
+ canMountSys := canMountSys(isRootless, isNewUserns, s)
if s.Privileged && canMountSys {
cgroupPerm = "rw"
@@ -232,6 +233,8 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
g.AddMount(devPts)
}
+ inUserNS := isRootless || isNewUserns
+
if inUserNS && s.IpcNS.IsHost() {
g.RemoveMount("/dev/mqueue")
devMqueue := spec.Mount{
diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go
index 0c74bf972..71b4c0089 100644
--- a/test/e2e/build_test.go
+++ b/test/e2e/build_test.go
@@ -234,7 +234,7 @@ RUN printenv http_proxy`
})
It("podman build and check identity", func() {
- session := podmanTest.Podman([]string{"build", "-f", "Containerfile.path", "--no-cache", "-t", "test", "build/basicalpine"})
+ session := podmanTest.Podman([]string{"build", "-f", "build/basicalpine/Containerfile.path", "--no-cache", "-t", "test", "build/basicalpine"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -244,4 +244,218 @@ RUN printenv http_proxy`
data := inspect.OutputToString()
Expect(data).To(ContainSubstring(buildah.Version))
})
+
+ It("podman remote test container/docker file is not inside context dir", func() {
+ // Given
+ // Switch to temp dir and restore it afterwards
+ cwd, err := os.Getwd()
+ Expect(err).To(BeNil())
+
+ podmanTest.AddImageToRWStore(ALPINE)
+
+ // Write target and fake files
+ targetPath, err := CreateTempDirInTempDir()
+ Expect(err).To(BeNil())
+ targetSubPath := filepath.Join(targetPath, "subdir")
+ err = os.Mkdir(targetSubPath, 0755)
+ Expect(err).To(BeNil())
+ dummyFile := filepath.Join(targetSubPath, "dummy")
+ err = ioutil.WriteFile(dummyFile, []byte("dummy"), 0644)
+ Expect(err).To(BeNil())
+
+ containerfile := `FROM quay.io/libpod/alpine:latest
+ADD . /test
+RUN find /test`
+
+ containerfilePath := filepath.Join(targetPath, "Containerfile")
+ err = ioutil.WriteFile(containerfilePath, []byte(containerfile), 0644)
+ Expect(err).To(BeNil())
+
+ defer func() {
+ Expect(os.Chdir(cwd)).To(BeNil())
+ Expect(os.RemoveAll(targetPath)).To(BeNil())
+ }()
+
+ // make cwd as context root path
+ Expect(os.Chdir(targetPath)).To(BeNil())
+
+ session := podmanTest.Podman([]string{"build", "-t", "test", "-f", "Containerfile", targetSubPath})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ ok, _ := session.GrepString("/test/dummy")
+ Expect(ok).To(BeTrue())
+ })
+
+ It("podman remote test container/docker file is not at root of context dir", func() {
+ if IsRemote() {
+ podmanTest.StopRemoteService()
+ podmanTest.StartRemoteService()
+ } else {
+ Skip("Only valid at remote test")
+ }
+ // Given
+ // Switch to temp dir and restore it afterwards
+ cwd, err := os.Getwd()
+ Expect(err).To(BeNil())
+
+ podmanTest.AddImageToRWStore(ALPINE)
+
+ // Write target and fake files
+ targetPath, err := CreateTempDirInTempDir()
+ Expect(err).To(BeNil())
+ targetSubPath := filepath.Join(targetPath, "subdir")
+ err = os.Mkdir(targetSubPath, 0755)
+ Expect(err).To(BeNil())
+
+ containerfile := `FROM quay.io/libpod/alpine:latest`
+
+ containerfilePath := filepath.Join(targetSubPath, "Containerfile")
+ err = ioutil.WriteFile(containerfilePath, []byte(containerfile), 0644)
+ Expect(err).To(BeNil())
+
+ defer func() {
+ Expect(os.Chdir(cwd)).To(BeNil())
+ Expect(os.RemoveAll(targetPath)).To(BeNil())
+ }()
+
+ // make cwd as context root path
+ Expect(os.Chdir(targetPath)).To(BeNil())
+
+ session := podmanTest.Podman([]string{"build", "-t", "test", "-f", "subdir/Containerfile", "."})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ })
+
+ It("podman remote test .dockerignore", func() {
+ if IsRemote() {
+ podmanTest.StopRemoteService()
+ podmanTest.StartRemoteService()
+ } else {
+ Skip("Only valid at remote test")
+ }
+ // Given
+ // Switch to temp dir and restore it afterwards
+ cwd, err := os.Getwd()
+ Expect(err).To(BeNil())
+
+ podmanTest.AddImageToRWStore(ALPINE)
+
+ // Write target and fake files
+ targetPath, err := CreateTempDirInTempDir()
+ Expect(err).To(BeNil())
+
+ containerfile := `FROM quay.io/libpod/alpine:latest
+ADD . /testfilter/
+RUN find /testfilter/`
+
+ containerfilePath := filepath.Join(targetPath, "Containerfile")
+ err = ioutil.WriteFile(containerfilePath, []byte(containerfile), 0644)
+ Expect(err).To(BeNil())
+
+ targetSubPath := filepath.Join(targetPath, "subdir")
+ err = os.Mkdir(targetSubPath, 0755)
+ Expect(err).To(BeNil())
+
+ dummyFile1 := filepath.Join(targetPath, "dummy1")
+ err = ioutil.WriteFile(dummyFile1, []byte("dummy1"), 0644)
+ Expect(err).To(BeNil())
+
+ dummyFile2 := filepath.Join(targetPath, "dummy2")
+ err = ioutil.WriteFile(dummyFile2, []byte("dummy2"), 0644)
+ Expect(err).To(BeNil())
+
+ dummyFile3 := filepath.Join(targetSubPath, "dummy3")
+ err = ioutil.WriteFile(dummyFile3, []byte("dummy3"), 0644)
+ Expect(err).To(BeNil())
+
+ defer func() {
+ Expect(os.Chdir(cwd)).To(BeNil())
+ Expect(os.RemoveAll(targetPath)).To(BeNil())
+ }()
+
+ // make cwd as context root path
+ Expect(os.Chdir(targetPath)).To(BeNil())
+
+ dockerignoreContent := `dummy1
+subdir**`
+ dockerignoreFile := filepath.Join(targetPath, ".dockerignore")
+
+ // test .dockerignore
+ By("Test .dockererignore")
+ err = ioutil.WriteFile(dockerignoreFile, []byte(dockerignoreContent), 0644)
+ Expect(err).To(BeNil())
+
+ session := podmanTest.Podman([]string{"build", "-t", "test", "."})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ ok, _ := session.GrepString("/testfilter/dummy1")
+ Expect(ok).NotTo(BeTrue())
+ ok, _ = session.GrepString("/testfilter/dummy2")
+ Expect(ok).To(BeTrue())
+ ok, _ = session.GrepString("/testfilter/subdir")
+ Expect(ok).NotTo(BeTrue()) //.dockerignore filters both subdir and inside subdir
+ ok, _ = session.GrepString("/testfilter/subdir/dummy3")
+ Expect(ok).NotTo(BeTrue())
+ })
+
+ It("podman remote test context dir contains empty dirs and symlinks", func() {
+ if IsRemote() {
+ podmanTest.StopRemoteService()
+ podmanTest.StartRemoteService()
+ } else {
+ Skip("Only valid at remote test")
+ }
+ // Given
+ // Switch to temp dir and restore it afterwards
+ cwd, err := os.Getwd()
+ Expect(err).To(BeNil())
+
+ podmanTest.AddImageToRWStore(ALPINE)
+
+ // Write target and fake files
+ targetPath, err := CreateTempDirInTempDir()
+ Expect(err).To(BeNil())
+ targetSubPath := filepath.Join(targetPath, "subdir")
+ err = os.Mkdir(targetSubPath, 0755)
+ Expect(err).To(BeNil())
+ dummyFile := filepath.Join(targetSubPath, "dummy")
+ err = ioutil.WriteFile(dummyFile, []byte("dummy"), 0644)
+ Expect(err).To(BeNil())
+
+ emptyDir := filepath.Join(targetSubPath, "emptyDir")
+ err = os.Mkdir(emptyDir, 0755)
+ Expect(err).To(BeNil())
+ Expect(os.Chdir(targetSubPath)).To(BeNil())
+ Expect(os.Symlink("dummy", "dummy-symlink")).To(BeNil())
+
+ containerfile := `FROM quay.io/libpod/alpine:latest
+ADD . /test
+RUN find /test
+RUN [[ -L /test/dummy-symlink ]] && echo SYMLNKOK || echo SYMLNKERR`
+
+ containerfilePath := filepath.Join(targetSubPath, "Containerfile")
+ err = ioutil.WriteFile(containerfilePath, []byte(containerfile), 0644)
+ Expect(err).To(BeNil())
+
+ defer func() {
+ Expect(os.Chdir(cwd)).To(BeNil())
+ Expect(os.RemoveAll(targetPath)).To(BeNil())
+ }()
+
+ // make cwd as context root path
+ Expect(os.Chdir(targetPath)).To(BeNil())
+
+ session := podmanTest.Podman([]string{"build", "-t", "test", targetSubPath})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ ok, _ := session.GrepString("/test/dummy")
+ Expect(ok).To(BeTrue())
+ ok, _ = session.GrepString("/test/emptyDir")
+ Expect(ok).To(BeTrue())
+ ok, _ = session.GrepString("/test/dummy-symlink")
+ Expect(ok).To(BeTrue())
+ ok, _ = session.GrepString("SYMLNKOK")
+ Expect(ok).To(BeTrue())
+ })
+
})
diff --git a/test/e2e/pod_stats_test.go b/test/e2e/pod_stats_test.go
index 287830102..1709b4f81 100644
--- a/test/e2e/pod_stats_test.go
+++ b/test/e2e/pod_stats_test.go
@@ -17,7 +17,7 @@ var _ = Describe("Podman pod stats", func() {
)
BeforeEach(func() {
- SkipIfRootless("Tests fail with both CGv1/2 + required --cgroup-manager=cgroupfs")
+ SkipIfRootlessCgroupsV1("Tests fail with both CGv1 + required --cgroup-manager=cgroupfs")
if isContainerized() {
SkipIfCgroupV1("All tests fail Error: unable to load cgroup at ...: cgroup deleted")
}
@@ -176,8 +176,7 @@ var _ = Describe("Podman pod stats", func() {
})
It("podman stats on net=host post", func() {
- // --net=host not supported for rootless pods at present
- SkipIfRootlessCgroupsV1("Pause stats not supported in cgroups v1")
+ SkipIfRootless("--net=host not supported for rootless pods at present")
podName := "testPod"
podCreate := podmanTest.Podman([]string{"pod", "create", "--net=host", "--name", podName})
podCreate.WaitWithDefaultTimeout()
diff --git a/test/e2e/rename_test.go b/test/e2e/rename_test.go
index 324e6a54a..7affbaf56 100644
--- a/test/e2e/rename_test.go
+++ b/test/e2e/rename_test.go
@@ -17,7 +17,6 @@ var _ = Describe("podman rename", func() {
)
BeforeEach(func() {
- SkipIfRemote("Rename not yet implemented by podman-remote")
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
diff --git a/test/e2e/run_ns_test.go b/test/e2e/run_ns_test.go
index 51657cb1e..29d2d4395 100644
--- a/test/e2e/run_ns_test.go
+++ b/test/e2e/run_ns_test.go
@@ -105,6 +105,14 @@ var _ = Describe("Podman run ns", func() {
Expect(session).To(ExitWithError())
})
+ It("podman run mounts fresh cgroup", func() {
+ session := podmanTest.Podman([]string{"run", fedoraMinimal, "grep", "cgroup", "/proc/self/mountinfo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ output := session.OutputToString()
+ Expect(output).ToNot(ContainSubstring(".."))
+ })
+
It("podman run --ipc=host --pid=host", func() {
SkipIfRootlessCgroupsV1("Not supported for rootless + CGroupsV1")
cmd := exec.Command("ls", "-l", "/proc/self/ns/pid")