Skip to content

Commit

Permalink
Adding new implementation for parsing volumen input when running on
Browse files Browse the repository at this point in the history
darwin. This is important because docker 26 did a refactoring and
safepath.Join is not available for darwin. This is a workaround for now

Signed-off-by: Juan Bustamante <jbustamante@vmware.com>
  • Loading branch information
jjbustamante committed Apr 24, 2024
1 parent 4163bbf commit 3c6dc12
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 27 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ require (
github.com/moby/sys/user v0.1.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/selinux v1.11.0 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/prometheus/client_golang v1.19.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
Expand Down
26 changes: 0 additions & 26 deletions pkg/client/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"github.com/buildpacks/imgutil/local"
"github.com/buildpacks/imgutil/remote"
"github.com/buildpacks/lifecycle/platform/files"
"github.com/docker/cli/cli/compose/loader"
types "github.com/docker/docker/api/types/image"
"github.com/google/go-containerregistry/pkg/name"
"github.com/pkg/errors"
Expand Down Expand Up @@ -1377,31 +1376,6 @@ func randString(n int) string {
return string(b)
}

func processVolumes(imgOS string, volumes []string) (processed []string, warnings []string, err error) {
for _, v := range volumes {
volume, err := loader.ParseVolume(v)
if err != nil {
return nil, nil, errors.Wrapf(err, "platform volume %q has invalid format", v)
}

sensitiveDirs := []string{"/cnb", "/layers"}
if imgOS == "windows" {
sensitiveDirs = []string{`c:/cnb`, `c:\cnb`, `c:/layers`, `c:\layers`}
}
for _, p := range sensitiveDirs {
if strings.HasPrefix(strings.ToLower(volume.Target), p) {
warnings = append(warnings, fmt.Sprintf("Mounting to a sensitive directory %s", style.Symbol(volume.Target)))
}
mode := "ro"
if !volume.ReadOnly {
mode = "rw"
}
processed = append(processed, fmt.Sprintf("%s:%s:%s", volume.Source, volume.Target, mode))
}
}
return processed, warnings, nil
}

func (c *Client) logImageNameAndSha(ctx context.Context, publish bool, imageRef name.Reference) error {
// The image name and sha are printed in the lifecycle logs, and there is no need to print it again, unless output is suppressed.
if !logging.IsQuiet(c.logger) {
Expand Down
6 changes: 5 additions & 1 deletion pkg/client/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2763,7 +2763,11 @@ api = "0.2"
Volumes: []string{":::"},
},
})
h.AssertError(t, err, `platform volume ":::" has invalid format: invalid volume specification: ':::'`)
if runtime.GOOS == "darwin" {
h.AssertError(t, err, `platform volume ":::" has invalid format: invalid spec: :::: empty section between colons`)
} else {
h.AssertError(t, err, `platform volume ":::" has invalid format: invalid volume specification: ':::'`)
}
})
})

Expand Down
53 changes: 53 additions & 0 deletions pkg/client/process_volumes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//go:build linux || windows

package client

import (
"fmt"
"runtime"
"strings"

"github.com/docker/docker/volume/mounts"
"github.com/pkg/errors"

"github.com/buildpacks/pack/internal/style"
)

func processVolumes(imgOS string, volumes []string) (processed []string, warnings []string, err error) {
var parser mounts.Parser
switch "windows" {
case imgOS:
parser = mounts.NewWindowsParser()
case runtime.GOOS:
parser = mounts.NewLCOWParser()
default:
parser = mounts.NewLinuxParser()
}
for _, v := range volumes {
volume, err := parser.ParseMountRaw(v, "")
if err != nil {
return nil, nil, errors.Wrapf(err, "platform volume %q has invalid format", v)
}

sensitiveDirs := []string{"/cnb", "/layers"}
if imgOS == "windows" {
sensitiveDirs = []string{`c:/cnb`, `c:\cnb`, `c:/layers`, `c:\layers`}
}
for _, p := range sensitiveDirs {
if strings.HasPrefix(strings.ToLower(volume.Spec.Target), p) {
warnings = append(warnings, fmt.Sprintf("Mounting to a sensitive directory %s", style.Symbol(volume.Spec.Target)))
}
}

processed = append(processed, fmt.Sprintf("%s:%s:%s", volume.Spec.Source, volume.Spec.Target, processMode(volume.Mode)))
}
return processed, warnings, nil
}

func processMode(mode string) string {
if mode == "" {
return "ro"
}

return mode
}
51 changes: 51 additions & 0 deletions pkg/client/process_volumes_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package client

import (
"fmt"
"strings"

"github.com/docker/cli/cli/compose/loader"
"github.com/docker/cli/cli/compose/types"
"github.com/pkg/errors"

"github.com/buildpacks/pack/internal/style"
)

func processVolumes(imgOS string, volumes []string) (processed []string, warnings []string, err error) {
for _, v := range volumes {
volume, err := parseVolume(v)
if err != nil {
return nil, nil, err
}
sensitiveDirs := []string{"/cnb", "/layers"}
if imgOS == "windows" {
sensitiveDirs = []string{`c:/cnb`, `c:\cnb`, `c:/layers`, `c:\layers`}
}

Check warning on line 23 in pkg/client/process_volumes_darwin.go

View check run for this annotation

Codecov / codecov/patch

pkg/client/process_volumes_darwin.go#L22-L23

Added lines #L22 - L23 were not covered by tests
for _, p := range sensitiveDirs {
if strings.HasPrefix(strings.ToLower(volume.Target), p) {
warnings = append(warnings, fmt.Sprintf("Mounting to a sensitive directory %s", style.Symbol(volume.Target)))
}
}
mode := "ro"
if strings.HasSuffix(v, ":rw") && !volume.ReadOnly {
mode = "rw"
}
processed = append(processed, fmt.Sprintf("%s:%s:%s", volume.Source, volume.Target, mode))
}
return processed, warnings, nil
}

func parseVolume(volume string) (types.ServiceVolumeConfig, error) {
// volume format: '<host path>:<target path>[:<options>]'
split := strings.Split(volume, ":")
if len(split) == 3 {
if split[2] != "ro" && split[2] != "rw" && !strings.Contains(split[2], "volume-opt") {
return types.ServiceVolumeConfig{}, errors.New(fmt.Sprintf("platform volume %q has invalid format: invalid mode: %s", volume, split[2]))
}
}
config, err := loader.ParseVolume(volume)
if err != nil {
return config, errors.Wrapf(err, "platform volume %q has invalid format", volume)
}
return config, nil
}

0 comments on commit 3c6dc12

Please sign in to comment.