fix: failed to create local dir x permission denied (#2880)

* fix: failed to copy absolute file: failed to create local dir x permission denied

Signed-off-by: William Wang <williamw0825@gmail.com>

* docs: make log msg more accurate

Signed-off-by: William Wang <williamw0825@gmail.com>

* feat: ensure mode of dir when using src as dir in copy module

Signed-off-by: William Wang <williamw0825@gmail.com>

* refactor: change func name to ensureDestDirMode

Signed-off-by: William Wang <williamw0825@gmail.com>

* fix: pass go lint

Signed-off-by: William Wang <williamw0825@gmail.com>

---------

Signed-off-by: William Wang <williamw0825@gmail.com>
This commit is contained in:
William Wang 2025-12-09 17:39:18 +08:00 committed by GitHub
parent b7f6e19045
commit 992a2259df
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 42 additions and 28 deletions

View File

@ -113,8 +113,8 @@ func (c *kubernetesConnector) PutFile(_ context.Context, src []byte, dst string,
if !os.IsNotExist(err) {
return errors.Wrapf(err, "failed to stat local dir %q for cluster %q", dst, c.clusterName)
}
if err := os.MkdirAll(filepath.Dir(dst), mode); err != nil {
return errors.Wrapf(err, "failed to create local dir %q for cluster %q", dst, c.clusterName)
if err := os.MkdirAll(filepath.Dir(dst), _const.PermDirPublic); err != nil {
return errors.Wrapf(err, "failed to create local dir of path %q for cluster %q", dst, c.clusterName)
}
}
if err := os.WriteFile(dst, src, mode); err != nil {

View File

@ -80,8 +80,8 @@ func (c *localConnector) PutFile(_ context.Context, src []byte, dst string, mode
if !os.IsNotExist(err) {
return errors.Wrapf(err, "failed to stat local dir %q", dst)
}
if err := os.MkdirAll(filepath.Dir(dst), mode); err != nil {
return errors.Wrapf(err, "failed to create local dir %q", dst)
if err := os.MkdirAll(filepath.Dir(dst), _const.PermDirPublic); err != nil {
return errors.Wrapf(err, "failed to create local dir of path %q", dst)
}
}
if err := os.WriteFile(dst, src, mode); err != nil {

View File

@ -16,6 +16,8 @@ limitations under the License.
package _const
import "os"
// variable specific key in system
const ( // === From Global Parameter ===
// VariableLocalHost is the default local host name in inventory.
@ -123,3 +125,8 @@ const (
// SSHVerifyStatusUnreachable means host server cannot connect to target ssh
SSHVerifyStatusUnreachable = "unreachable"
)
const (
// PermDirPublic means public permission of directory, something like os.ModePerm
PermDirPublic os.FileMode = 0755
)

View File

@ -217,7 +217,10 @@ func (ca copyArgs) handleRelativePath(ctx context.Context, options ExecOptions,
}
// copyAbsoluteDir copies all files from an absolute directory to the remote host.
func (ca copyArgs) copyAbsoluteDir(ctx context.Context, conn connector.Connector) error {
func (ca copyArgs) copyAbsoluteDir(ctx context.Context, conn connector.Connector) (resRrr error) {
defer func() {
resRrr = ca.ensureDestDirMode(ctx, conn)
}()
return filepath.WalkDir(ca.src, func(path string, d fs.DirEntry, err error) error {
// Only copy files, skip directories
if d.IsDir() {
@ -234,25 +237,20 @@ func (ca copyArgs) copyAbsoluteDir(ctx context.Context, conn connector.Connector
}
mode := info.Mode()
if ca.mode != nil {
mode = os.FileMode(*ca.mode)
}
// read file
data, err := os.ReadFile(path)
if err != nil {
return errors.Wrapf(err, "failed to read file %q", path)
}
// copy file to remote
dest := ca.dest
if strings.HasSuffix(ca.dest, "/") {
rel, err := filepath.Rel(ca.src, path)
if err != nil {
return errors.Wrap(err, "failed to get relative filepath")
}
dest = filepath.Join(ca.dest, rel)
rel, err := filepath.Rel(ca.src, path)
if err != nil {
return errors.Wrap(err, "failed to get relative filepath")
}
dest := filepath.Join(ca.dest, rel)
tmpDest := filepath.Join("/tmp", ca.dest)
tmpDest := filepath.Join("/tmp", dest)
if err = conn.PutFile(ctx, data, tmpDest, mode); err != nil {
return err
@ -265,7 +263,10 @@ func (ca copyArgs) copyAbsoluteDir(ctx context.Context, conn connector.Connector
}
// copyRelativeDir copies all files from a relative directory (in the project) to the remote host.
func (ca copyArgs) copyRelativeDir(ctx context.Context, pj project.Project, relPath string, conn connector.Connector) error {
func (ca copyArgs) copyRelativeDir(ctx context.Context, pj project.Project, relPath string, conn connector.Connector) (resRrr error) {
defer func() {
resRrr = ca.ensureDestDirMode(ctx, conn)
}()
return pj.WalkDir(relPath, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
@ -281,24 +282,19 @@ func (ca copyArgs) copyRelativeDir(ctx context.Context, pj project.Project, relP
}
mode := info.Mode()
if ca.mode != nil {
mode = os.FileMode(*ca.mode)
}
data, err := pj.ReadFile(path)
if err != nil {
return errors.Wrap(err, "failed to read file")
}
dest := ca.dest
if strings.HasSuffix(ca.dest, "/") {
rel, err := pj.Rel(relPath, path)
if err != nil {
return errors.Wrap(err, "failed to get relative file path")
}
dest = filepath.Join(ca.dest, rel)
rel, err := pj.Rel(relPath, path)
if err != nil {
return errors.Wrap(err, "failed to get relative file path")
}
tmpDest := filepath.Join("/tmp", ca.dest)
dest := filepath.Join(ca.dest, rel)
tmpDest := filepath.Join("/tmp", dest)
err = conn.PutFile(ctx, data, tmpDest, mode)
if err != nil {
@ -311,6 +307,17 @@ func (ca copyArgs) copyRelativeDir(ctx context.Context, pj project.Project, relP
})
}
// ensureDestDirMode if mode args exists, ensure dest dir mode after all files copied
func (ca copyArgs) ensureDestDirMode(ctx context.Context, conn connector.Connector) error {
if ca.mode != nil {
_, _, err := conn.ExecuteCommand(ctx, fmt.Sprintf("chmod %04o %s", *ca.mode, ca.dest))
if err != nil {
return err
}
}
return nil
}
// copyContent converts the content param and copies it to the destination file on the remote host.
func (ca copyArgs) copyContent(ctx context.Context, mode fs.FileMode, conn connector.Connector) (string, string, error) {
// Content must be copied to a file, not a directory