@@ -19,7 +19,7 @@ package containerd
1919import (
2020 "archive/tar"
2121 "context"
22- "errors "
22+ "os "
2323 "path/filepath"
2424
2525 introspectionapi "github.com/containerd/containerd/api/services/introspection/v1"
@@ -28,10 +28,11 @@ import (
2828 "github.com/containerd/containerd/content"
2929 "github.com/containerd/containerd/images"
3030 "github.com/containerd/containerd/platforms"
31+ "github.com/pkg/errors"
3132)
3233
3334// Install a binary image into the opt service
34- func (c * Client ) Install (ctx context.Context , image Image ) error {
35+ func (c * Client ) Install (ctx context.Context , image Image , opts ... InstallOpts ) error {
3536 resp , err := c .IntrospectionService ().Plugins (ctx , & introspectionapi.PluginsRequest {
3637 Filters : []string {
3738 "id==opt" ,
@@ -47,6 +48,10 @@ func (c *Client) Install(ctx context.Context, image Image) error {
4748 if path == "" {
4849 return errors .New ("opt path not exported" )
4950 }
51+ var config InstallConfig
52+ for _ , o := range opts {
53+ o (& config )
54+ }
5055 var (
5156 cs = image .ContentStore ()
5257 platform = platforms .Default ()
@@ -66,8 +71,18 @@ func (c *Client) Install(ctx context.Context, image Image) error {
6671 return err
6772 }
6873 defer r .Close ()
69- if _ , err := archive .Apply (ctx , path , r , archive .WithFilter (func (hdr * tar.Header ) bool {
70- return filepath .Dir (hdr .Name ) == "bin"
74+ if _ , err := archive .Apply (ctx , path , r , archive .WithFilter (func (hdr * tar.Header ) (bool , error ) {
75+ d := filepath .Dir (hdr .Name )
76+ result := d == "bin"
77+ if config .Libs {
78+ result = result || d == "lib"
79+ }
80+ if result && ! config .Replace {
81+ if _ , err := os .Lstat (filepath .Join (path , hdr .Name )); err == nil {
82+ return false , errors .Errorf ("cannot replace %s in %s" , hdr .Name , path )
83+ }
84+ }
85+ return result , nil
7186 })); err != nil {
7287 return err
7388 }
0 commit comments