diff --git a/pkg/connector/kubernetes_connector.go b/pkg/connector/kubernetes_connector.go index dae22f9f..2cbdfb9d 100644 --- a/pkg/connector/kubernetes_connector.go +++ b/pkg/connector/kubernetes_connector.go @@ -113,7 +113,7 @@ 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), os.ModePerm); err != nil { + 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) } } diff --git a/pkg/connector/local_connector.go b/pkg/connector/local_connector.go index de54e1b5..b16c04c5 100644 --- a/pkg/connector/local_connector.go +++ b/pkg/connector/local_connector.go @@ -80,7 +80,7 @@ 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), os.ModePerm); err != nil { + if err := os.MkdirAll(filepath.Dir(dst), _const.PermDirPublic); err != nil { return errors.Wrapf(err, "failed to create local dir of path %q", dst) } } diff --git a/pkg/const/common.go b/pkg/const/common.go index b34ce350..06ff018c 100644 --- a/pkg/const/common.go +++ b/pkg/const/common.go @@ -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,7 @@ const ( // SSHVerifyStatusUnreachable means host server cannot connect to target ssh SSHVerifyStatusUnreachable = "unreachable" ) + +const ( + PermDirPublic = os.FileMode(0755) +) diff --git a/pkg/modules/copy.go b/pkg/modules/copy.go index 9f8c3ed4..3f355345 100644 --- a/pkg/modules/copy.go +++ b/pkg/modules/copy.go @@ -218,6 +218,7 @@ 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 { + defer ca.ensureDestMode(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 +235,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 @@ -266,6 +262,7 @@ 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 { + defer ca.ensureDestMode(ctx, conn) return pj.WalkDir(relPath, func(path string, d fs.DirEntry, err error) error { if err != nil { return err @@ -281,24 +278,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 +303,17 @@ func (ca copyArgs) copyRelativeDir(ctx context.Context, pj project.Project, relP }) } +// ensureDestMode if mode args exists, ensure dest dir mode after all files copied +func (ca copyArgs) ensureDestMode(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