Skip to content

Commit

Permalink
[BACKPORT 2.18.4][PLAT-9990] Allowing YBA-installer to work with arbi…
Browse files Browse the repository at this point in the history
…trary umask

Summary:
Previously our implementation for making directories simply called go's os module which set permissions before umask, so any umask settings on the operating system would result in non deterministic behavior. This diff changes our common Mkdir implementation to explicitly set the permissions to whatever we desire.

Original diff: d2df3ad / D27912

Test Plan:
Validate diff fixes installation on a box with umask 027.
More test cases for making directories since the function is more complicated.

Reviewers: muthu, sanketh

Reviewed By: muthu

Subscribers: yugaware

Tags: #jenkins-ready

Differential Revision: https://phorge.dev.yugabyte.com/D29980
  • Loading branch information
shubin-yb committed Nov 6, 2023
1 parent 022c68e commit 77c3f32
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 26 deletions.
36 changes: 26 additions & 10 deletions managed/yba-installer/cmd/platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,16 +135,32 @@ func (plat Platform) SetDataDirPerms() error {
return nil
}

func (plat Platform) createNecessaryDirectories() {

common.MkdirAll(common.GetSoftwareRoot()+"/yb-platform", os.ModePerm)
common.MkdirAll(common.GetBaseInstall()+"/data/yb-platform/releases/"+plat.version, os.ModePerm)
common.MkdirAll(common.GetBaseInstall()+"/data/yb-platform/ybc/release", os.ModePerm)
common.MkdirAll(common.GetBaseInstall()+"/data/yb-platform/ybc/releases", os.ModePerm)
common.MkdirAll(common.GetBaseInstall()+"/data/yb-platform/node-agent/releases", os.ModePerm)

common.MkdirAll(plat.devopsDir(), os.ModePerm)
common.MkdirAll(plat.yugawareDir(), os.ModePerm)
func (plat Platform) createNecessaryDirectories() error {
dirs := []string{
common.GetSoftwareRoot() + "/yb-platform",
common.GetBaseInstall() + "/data/yb-platform/releases/" + plat.version,
common.GetBaseInstall() + "/data/yb-platform/ybc/release",
common.GetBaseInstall() + "/data/yb-platform/ybc/releases",
common.GetBaseInstall() + "/data/yb-platform/node-agent/releases",
plat.devopsDir(),
plat.yugawareDir(),
}
userName := viper.GetString("service_username")
for _, dir := range dirs {
if _, err := os.Stat(dir); errors.Is(err, os.ErrNotExist) {
if mkErr := common.MkdirAll(dir, common.DirMode); mkErr != nil {
log.Error("failed to make " + dir + ": " + err.Error())
return mkErr
}
if common.HasSudoAccess() {
if chErr := common.Chown(dir, userName, userName, true); chErr != nil {
log.Error("failed to set ownership of " + dir + ": " + chErr.Error())
return chErr
}
}
}
}
return nil
}

func (plat Platform) untarDevopsAndYugawarePackages() {
Expand Down
22 changes: 15 additions & 7 deletions managed/yba-installer/cmd/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,13 @@ func (prom Prometheus) Upgrade() error {

func (prom Prometheus) moveAndExtractPrometheusPackage() {

packagesPath := common.GetInstallerSoftwareDir() + "/packages"

srcPath := fmt.Sprintf(
"%s/third-party/prometheus-%s.linux-amd64.tar.gz", common.GetInstallerSoftwareDir(),
prom.version)
dstPath := fmt.Sprintf(
"%s/packages/prometheus-%s.linux-amd64.tar.gz", common.GetInstallerSoftwareDir(), prom.version)
"%s/prometheus-%s.linux-amd64.tar.gz", packagesPath, prom.version)

common.CopyFile(srcPath, dstPath)
rExtract, errExtract := os.Open(dstPath)
Expand All @@ -269,23 +271,29 @@ func (prom Prometheus) moveAndExtractPrometheusPackage() {

extPackagePath := fmt.Sprintf(
"%s/packages/prometheus-%s.linux-amd64", common.GetInstallerSoftwareDir(), prom.version)

if _, err := os.Stat(extPackagePath); err == nil {
log.Debug(extPackagePath + " already exists, skipping re-extract.")
} else {
if err := tar.Untar(rExtract, common.GetInstallerSoftwareDir()+"/packages",
tar.WithMaxUntarSize(-1)); err != nil {
if err := tar.Untar(rExtract, packagesPath, tar.WithMaxUntarSize(-1)); err != nil {
log.Fatal(fmt.Sprintf("failed to extract file %s, error: %s", dstPath, err.Error()))
}
log.Debug(dstPath + " successfully extracted.")
}

if common.HasSudoAccess() {
userName := viper.GetString("service_username")
if err := common.Chown(packagesPath, userName, userName, true); err != nil {
log.Fatal(fmt.Sprintf("failed to change ownership of %s: %s", packagesPath, err.Error()))
}
}
}

func (prom Prometheus) createDataDirs() {

common.MkdirAll(prom.DataDir+"/storage", os.ModePerm)
common.MkdirAll(prom.DataDir+"/swamper_targets", os.ModePerm)
common.MkdirAll(prom.DataDir+"/swamper_rules", os.ModePerm)
common.MkdirAll(prom.DataDir+"/storage", common.DirMode)
common.MkdirAll(prom.DataDir+"/swamper_targets", common.DirMode)
common.MkdirAll(prom.DataDir+"/swamper_rules", common.DirMode)
log.Debug(prom.DataDir + "/storage /swamper_targets /swamper_rules" + " directories created.")

// Create the log file
Expand All @@ -311,7 +319,7 @@ func (prom Prometheus) createPrometheusSymlinks() {
promBinaryDir = "/usr/local/bin"
} else {
// promBinaryDir doesn't exist for non-root mode, lets create it.
common.MkdirAll(promBinaryDir, os.ModePerm)
common.MkdirAll(promBinaryDir, common.DirMode)
}

common.CreateSymlink(promPkg, promBinaryDir, "prometheus")
Expand Down
18 changes: 12 additions & 6 deletions managed/yba-installer/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,22 +55,28 @@ func Install(version string) {

func createInstallDirs() {
createDirs := []string{
GetBaseInstall(),
GetSoftwareRoot(),
dm.WorkingDirectory(),
filepath.Join(GetBaseInstall(), "data"),
filepath.Join(GetBaseInstall(), "data/logs"),
GetInstallerSoftwareDir(),
}

for _, dir := range createDirs {
if err := MkdirAll(dir, os.ModePerm); err != nil {
log.Fatal(fmt.Sprintf("failed creating directory %s: %s", dir, err.Error()))
_, err := os.Stat(dir)
if os.IsNotExist(err) {
if err := MkdirAll(dir, DirMode); err != nil {
log.Fatal(fmt.Sprintf("failed creating directory %s: %s", dir, err.Error()))
}
}
// Only change ownership for root installs.
if HasSudoAccess() {
err := Chown(dir, viper.GetString("service_username"), viper.GetString("service_username"), true)
serviceuser := viper.GetString("service_username")
err := Chown(dir, serviceuser, serviceuser, true)
if err != nil {
log.Fatal("failed to change ownership of " + dir + " to " +
viper.GetString("service_username") + ": " + err.Error())
serviceuser + ": " + err.Error())
}
}
}
Expand All @@ -85,7 +91,7 @@ func createUpgradeDirs() {
}

for _, dir := range createDirs {
if err := MkdirAll(dir, os.ModePerm); err != nil {
if err := MkdirAll(dir, DirMode); err != nil {
log.Fatal(fmt.Sprintf("failed creating directory %s: %s", dir, err.Error()))
}
if HasSudoAccess() {
Expand Down Expand Up @@ -348,7 +354,7 @@ func generateSelfSignedCerts() (string, string) {
caCertPath := filepath.Join(certsDir, "ca_cert.pem")
caKeyPath := filepath.Join(certsDir, "ca_key.pem")

err := MkdirAll(certsDir, os.ModePerm)
err := MkdirAll(certsDir, DirMode)
if err != nil && !os.IsExist(err) {
log.Fatal(fmt.Sprintf("Unable to create dir %s", certsDir))
}
Expand Down
3 changes: 3 additions & 0 deletions managed/yba-installer/common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ const ServerCertPath string = "server-cert.pem"
const ServerKeyPath string = "server-key.pem"

const ServerPemPath string = "server.pem"

// DirMode is the default permissions for a newly created directory.
const DirMode = 0755
3 changes: 2 additions & 1 deletion managed/yba-installer/common/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ func HasSudoAccess() bool {
// Create a file at a relative path for the non-root case. Have to make the directory before
// inserting the file in that directory.
func Create(p string) (*os.File, error) {
if err := MkdirAll(filepath.Dir(p), 0777); err != nil {
log.Debug("creating file (and parent directories) " + p)
if err := MkdirAll(filepath.Dir(p), DirMode); err != nil {
log.Fatal(fmt.Sprintf("Error creating %s. Failed with %s", p, err.Error()))
return nil, err
}
Expand Down
48 changes: 47 additions & 1 deletion managed/yba-installer/common/wrapper_utils.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package common

import (
"errors"
"fmt"
"os"
"os/user"
"path/filepath"

log "github.com/yugabyte/yugabyte-db/managed/yba-installer/logging"
)
Expand All @@ -15,7 +17,51 @@ import (

func MkdirAll(path string, perm os.FileMode) error {
log.Debug(fmt.Sprintf("Creating dir %s", path))
return os.MkdirAll(path, perm)
err := os.Mkdir(path, os.ModePerm)
if err == nil {
// change modification bits as well
if e := os.Chmod(path, perm); e != nil {
return e
}
return nil
} else if errors.Is(err, os.ErrExist) {
log.Debug(fmt.Sprintf("Dir %s already exists. Skipping creation.", path))
return nil
} else if _, ok := err.(*os.PathError); ok {
// recursive case where we need to make parent directories
return mkdirAllHelper(filepath.Dir(path), []string{filepath.Base(path)}, perm)
}
return err
}

func mkdirAllHelper(path string, children []string, perm os.FileMode) error {
log.Debug("Creating directory " + path)
err := os.Mkdir(path, os.ModePerm)
if err != nil {
// Directory can not be created at this level. More parents must be created.
// Appending to list so first directory that can be created will be at the end.
children = append(children, filepath.Base(path))
return mkdirAllHelper(filepath.Dir(path), children, perm)
}
// change modification bits as well
if e := os.Chmod(path, perm); e != nil {
return fmt.Errorf("error changing %s permissions to %d err: %s", path, perm, e.Error())
}
// Also make children
// Iterate in reverse because we appended all children starting with the deepest
// so first child is last.
for i := len(children) - 1; i >= 0; i-- {
path = path + string(os.PathSeparator) + children[i]
log.Debug("Creating directory " + path)
if e := os.Mkdir(path, os.ModePerm); err != nil && !errors.Is(err, os.ErrExist) {
return fmt.Errorf("error making %s: %s", path, e.Error())
}
// change modification bits as well
if e := os.Chmod(path, perm); e != nil {
return fmt.Errorf("error changing %s permissions to %d err: %s", path, perm, e.Error())
}
}
return nil
}

func RenameOrFail(src string, dst string) {
Expand Down
50 changes: 50 additions & 0 deletions managed/yba-installer/common/wrapper_utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package common

import (
"testing"
"os"
)

const CustomDirPerms = 0700 + os.ModeDir

func TestCreateNestedDirectory(t *testing.T) {
tmpDir := t.TempDir()
testdir := tmpDir + "/food/bar/baz"
err := MkdirAll(testdir, CustomDirPerms)
if err != nil {
t.Fatalf("error making directory %s: %s", testdir, err.Error())
}
ValidateDirectory(t, testdir, CustomDirPerms)
}

func TestCreateDirectory(t *testing.T) {
tmpDir := t.TempDir()
testdir := tmpDir + "/test"
err := MkdirAll(testdir, CustomDirPerms)
if err != nil {
t.Fatalf("error making directory %s: %s", testdir, err.Error())
}
ValidateDirectory(t, testdir, CustomDirPerms)
}

func TestCreateExistingDirectory(t *testing.T) {
testdir := t.TempDir()
testDirInfo, _ := os.Stat(testdir)
testDirPerms := testDirInfo.Mode()
err := MkdirAll(testdir, CustomDirPerms)
if err != nil {
t.Fatalf("error making directory %s: %s", testdir, err.Error())
}
ValidateDirectory(t, testdir, testDirPerms)
}

func ValidateDirectory(t *testing.T, testdir string, perm os.FileMode) {
fileInfo, err := os.Stat(testdir)
if err != nil {
t.Fatalf("error locating directory %s: %s", testdir, err.Error())
}
if fileInfo.Mode() != perm {
t.Fatalf("directory %s has incorrect permissions. expected: %s actual: %s",
testdir, perm, fileInfo.Mode())
}
}
2 changes: 1 addition & 1 deletion managed/yba-installer/components/ybactl/ybactl.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func New() *YbaCtlComponent {

// Setup will create the base install directory needed for initialization.
func (yc *YbaCtlComponent) Setup() error {
err := common.MkdirAll(common.YbactlInstallDir(), 0755)
err := common.MkdirAll(common.YbactlInstallDir(), common.DirMode)
return err
}

Expand Down

0 comments on commit 77c3f32

Please sign in to comment.