Add lib support as an option

Some images like `criu` will have extra libs that it requires.  This
adds lib support via LD_LIBRARY_PATH and InstallOpts

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2018-08-01 15:49:39 -04:00
parent 1537f31381
commit 5a47c5ec1d
9 changed files with 101 additions and 11 deletions

View File

@ -158,7 +158,11 @@ func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyO
// Normalize name, for safety and for a simple is-root check // Normalize name, for safety and for a simple is-root check
hdr.Name = filepath.Clean(hdr.Name) hdr.Name = filepath.Clean(hdr.Name)
if !options.Filter(hdr) { accept, err := options.Filter(hdr)
if err != nil {
return 0, err
}
if !accept {
continue continue
} }

View File

@ -22,11 +22,11 @@ import "archive/tar"
type ApplyOpt func(options *ApplyOptions) error type ApplyOpt func(options *ApplyOptions) error
// Filter specific files from the archive // Filter specific files from the archive
type Filter func(*tar.Header) bool type Filter func(*tar.Header) (bool, error)
// all allows all files // all allows all files
func all(_ *tar.Header) bool { func all(_ *tar.Header) (bool, error) {
return true return true, nil
} }
// WithFilter uses the filter to select which files are to be extracted. // WithFilter uses the filter to select which files are to be extracted.

View File

@ -17,6 +17,7 @@
package install package install
import ( import (
"github.com/containerd/containerd"
"github.com/containerd/containerd/cmd/ctr/commands" "github.com/containerd/containerd/cmd/ctr/commands"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
@ -27,6 +28,16 @@ var Command = cli.Command{
Usage: "install a new package", Usage: "install a new package",
ArgsUsage: "<ref>", ArgsUsage: "<ref>",
Description: "install a new package", Description: "install a new package",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "libs,l",
Usage: "install libs from the image",
},
cli.BoolFlag{
Name: "replace,r",
Usage: "replace any binaries or libs in the opt directory",
},
},
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
client, ctx, cancel, err := commands.NewClient(context) client, ctx, cancel, err := commands.NewClient(context)
if err != nil { if err != nil {
@ -38,6 +49,13 @@ var Command = cli.Command{
if err != nil { if err != nil {
return err return err
} }
return client.Install(ctx, image) var opts []containerd.InstallOpts
if context.Bool("libs") {
opts = append(opts, containerd.WithInstallLibs)
}
if context.Bool("replace") {
opts = append(opts, containerd.WithInstallReplace)
}
return client.Install(ctx, image, opts...)
}, },
} }

View File

@ -19,7 +19,7 @@ package containerd
import ( import (
"archive/tar" "archive/tar"
"context" "context"
"errors" "os"
"path/filepath" "path/filepath"
introspectionapi "github.com/containerd/containerd/api/services/introspection/v1" introspectionapi "github.com/containerd/containerd/api/services/introspection/v1"
@ -28,10 +28,11 @@ import (
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/pkg/errors"
) )
// Install a binary image into the opt service // Install a binary image into the opt service
func (c *Client) Install(ctx context.Context, image Image) error { func (c *Client) Install(ctx context.Context, image Image, opts ...InstallOpts) error {
resp, err := c.IntrospectionService().Plugins(ctx, &introspectionapi.PluginsRequest{ resp, err := c.IntrospectionService().Plugins(ctx, &introspectionapi.PluginsRequest{
Filters: []string{ Filters: []string{
"id==opt", "id==opt",
@ -47,6 +48,10 @@ func (c *Client) Install(ctx context.Context, image Image) error {
if path == "" { if path == "" {
return errors.New("opt path not exported") return errors.New("opt path not exported")
} }
var config InstallConfig
for _, o := range opts {
o(&config)
}
var ( var (
cs = image.ContentStore() cs = image.ContentStore()
platform = platforms.Default() platform = platforms.Default()
@ -66,8 +71,18 @@ func (c *Client) Install(ctx context.Context, image Image) error {
return err return err
} }
defer r.Close() defer r.Close()
if _, err := archive.Apply(ctx, path, r, archive.WithFilter(func(hdr *tar.Header) bool { if _, err := archive.Apply(ctx, path, r, archive.WithFilter(func(hdr *tar.Header) (bool, error) {
return filepath.Dir(hdr.Name) == "bin" d := filepath.Dir(hdr.Name)
result := d == "bin"
if config.Libs {
result = result || d == "lib"
}
if result && !config.Replace {
if _, err := os.Lstat(filepath.Join(path, hdr.Name)); err == nil {
return false, errors.Errorf("cannot replace %s in %s", hdr.Name, path)
}
}
return result, nil
})); err != nil { })); err != nil {
return err return err
} }

38
install_opts.go Normal file
View File

@ -0,0 +1,38 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package containerd
// InstallOpts configures binary installs
type InstallOpts func(*InstallConfig)
// InstallConfig sets the binary install configuration
type InstallConfig struct {
// Libs installs libs from the image
Libs bool
// Replace will overwrite existing binaries or libs in the opt directory
Replace bool
}
// WithInstallLibs installs libs from the image
func WithInstallLibs(c *InstallConfig) {
c.Libs = true
}
// WithInstallReplace will replace existing files
func WithInstallReplace(c *InstallConfig) {
c.Replace = true
}

View File

@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"runtime"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -49,6 +50,15 @@ func init() {
if err := os.Setenv("PATH", fmt.Sprintf("%s:%s", bin, os.Getenv("PATH"))); err != nil { if err := os.Setenv("PATH", fmt.Sprintf("%s:%s", bin, os.Getenv("PATH"))); err != nil {
return nil, errors.Wrapf(err, "set binary image directory in path %s", bin) return nil, errors.Wrapf(err, "set binary image directory in path %s", bin)
} }
if runtime.GOOS != "windows" {
lib := filepath.Join(path, "lib")
if err := os.MkdirAll(lib, 0711); err != nil {
return nil, err
}
if err := os.Setenv("LD_LIBRARY_PATH", fmt.Sprintf("%s:%s", os.Getenv("LD_LIBRARY_PATH"), lib)); err != nil {
return nil, errors.Wrapf(err, "set binary lib directory in path %s", lib)
}
}
return &manager{}, nil return &manager{}, nil
}, },
}) })

View File

@ -1,4 +1,4 @@
github.com/containerd/go-runc 14606eb66abd9e834e3bd22a4f5f46a3aad54c54 github.com/containerd/go-runc edcf3de1f4971445c42d61f20d506b30612aa031
github.com/containerd/console 4d8a41f4ce5b9bae77c41786ea2458330f43f081 github.com/containerd/console 4d8a41f4ce5b9bae77c41786ea2458330f43f081
github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2 github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40

View File

@ -18,6 +18,7 @@ package runc
import ( import (
"context" "context"
"os"
"os/exec" "os/exec"
"syscall" "syscall"
) )
@ -31,6 +32,7 @@ func (r *Runc) command(context context.Context, args ...string) *exec.Cmd {
cmd.SysProcAttr = &syscall.SysProcAttr{ cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: r.Setpgid, Setpgid: r.Setpgid,
} }
cmd.Env = os.Environ()
if r.PdeathSignal != 0 { if r.PdeathSignal != 0 {
cmd.SysProcAttr.Pdeathsig = r.PdeathSignal cmd.SysProcAttr.Pdeathsig = r.PdeathSignal
} }

View File

@ -20,6 +20,7 @@ package runc
import ( import (
"context" "context"
"os"
"os/exec" "os/exec"
) )
@ -28,5 +29,7 @@ func (r *Runc) command(context context.Context, args ...string) *exec.Cmd {
if command == "" { if command == "" {
command = DefaultCommand command = DefaultCommand
} }
return exec.CommandContext(context, command, append(r.args(), args...)...) cmd := exec.CommandContext(context, command, append(r.args(), args...)...)
cmd.Env = os.Environ()
return cmd
} }