-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cloudfuse service linux cmd #338
base: main
Are you sure you want to change the base?
Conversation
…le into the /etc/systemd/system/
cmd/service_linux.go
Outdated
} | ||
|
||
folderList := strings.Split(mountPath, "/") | ||
newFile, err := os.Create("/etc/systemd/system/" + folderList[len(folderList)-1] + ".service") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you set this as a constant to refer to at the top of the file.
cmd/service_linux.go
Outdated
} | ||
|
||
// get a list of group from reference user | ||
groups, err := usr.GroupIds() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What groups do we need to add the user to? And why do we need to add them manually?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the service user at least needs the current user added to its groups to be able to access and use mount and config file typically located at the end user's home directory. There doesn't seem to be a way around using the usermod command for this.
-changed collectServiceData() to extractValue() that outputs value from file for provided key -changed setUser() to use SUDO_USER env variable to add to service user group. and adjusted permissions for service user.
-corrected typo of moutingpoint that came from cloudfuse.service template file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great improvements!!
mountPathInfo, err := os.Stat(mountPath) | ||
if err != nil { | ||
return fmt.Errorf("failed to stat file: %v", err) | ||
} | ||
|
||
// Get file's group ID | ||
stat, ok = mountPathInfo.Sys().(*syscall.Stat_t) | ||
if !ok { | ||
return fmt.Errorf("failed to get file system stats") | ||
} | ||
mountGroupID := stat.Gid | ||
|
||
// Get configFileGroup name | ||
mountPathGroup, err := user.LookupGroupId(fmt.Sprint(mountGroupID)) | ||
if err != nil { | ||
return fmt.Errorf("failed to lookup group: %v", err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And can we do the same for the mount directory (just make sure the service user has the access it needs)?
if err != nil { | ||
if strings.Contains(err.Error(), "unknown user") { | ||
//create the user | ||
userAddCmd := exec.Command("sudo", "useradd", "-m", serviceUser) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably shouldn't use sudo
in our code. The user will already run our CLI with sudo, right?
//add group to serviceUser group | ||
usermodCmd := exec.Command("sudo", "usermod", "-aG", configFileGroup.Name, serviceUser) | ||
err = usermodCmd.Run() | ||
if err != nil { | ||
return fmt.Errorf("failed to create user due to following error: [%s]", err.Error()) | ||
} | ||
usermodCmd = exec.Command("sudo", "usermod", "-aG", mountPathGroup.Name, serviceUser) | ||
err = usermodCmd.Run() | ||
if err != nil { | ||
return fmt.Errorf("failed to create user due to following error: [%s]", err.Error()) | ||
} | ||
|
||
//set set folder permission on the mount path | ||
chmodCmd := exec.Command("sudo", "chmod", "770", mountPath) | ||
err = chmodCmd.Run() | ||
if err != nil { | ||
return fmt.Errorf("failed set permisions on mount path due to following error: [%s]", err.Error()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can suggest these commands on error, instead of doing them ourselves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. I think that makes it a bit easier and prevents us from doing something wrong to the users system.
folderList := strings.Split(mountPath, "/") | ||
serviceName := folderList[len(folderList)-1] + ".service" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once you get the absolute path for the mount folder, you could ensure the service name is perfectly specific and unique by just replacing slashes with dashes.
This is already the best practice / standard for mounts on startup using systemd.
newFile, err := os.Create("/etc/systemd/system/" + serviceName) | ||
if err != nil { | ||
return "", fmt.Errorf("error creating new service file: [%s]", err.Error()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you overwrite it, in case they want to use the install command to update an existing service?
Or would you rather they uninstall first?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few more comments to simplify some of this. Also, I tend to agree with Michael that we probably should not run a lot of these commands ourselves, and instead suggest them to the user. Also, there are a variety of lint and spelling errors that should be fixed.
cmd/service_linux.go
Outdated
var installCmd = &cobra.Command{ | ||
Use: "install", | ||
Short: "Installs a service file for a single mount with Cloudfuse. Requires elevated permissions.", | ||
Long: "Installs a service file for a single mount with Cloudfuse which remounts any active previously active mounts on startup. elevated permissions.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should say "Requires elevated permissions."
cmd/service_linux.go
Outdated
return fmt.Errorf("error: [%s]", err.Error()) | ||
} | ||
|
||
if strings.Contains(mountPath, ".") || strings.Contains(mountPath, "..") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than checking for dots, you could also use the go function filepath.IsAbs. And then you could also call filepath.Clean to get the shortest filepath if it not an absolute path.
RunE: func(cmd *cobra.Command, args []string) error { | ||
|
||
// get absolute path of provided relative mount path | ||
if strings.Contains(serviceName, ".") || strings.Contains(serviceName, "..") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is mostly the same as above, you could possibly abstract this type of logic into a separate function.
if err != nil { | ||
if strings.Contains(err.Error(), "unknown user") { | ||
//create the user | ||
userAddCmd := exec.Command("sudo", "useradd", "-m", serviceUser) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should user "-r" instead of "-m" since "-m" will create a user that has a home directory and we probably don't want to do that.
//add group to serviceUser group | ||
usermodCmd := exec.Command("sudo", "usermod", "-aG", configFileGroup.Name, serviceUser) | ||
err = usermodCmd.Run() | ||
if err != nil { | ||
return fmt.Errorf("failed to create user due to following error: [%s]", err.Error()) | ||
} | ||
usermodCmd = exec.Command("sudo", "usermod", "-aG", mountPathGroup.Name, serviceUser) | ||
err = usermodCmd.Run() | ||
if err != nil { | ||
return fmt.Errorf("failed to create user due to following error: [%s]", err.Error()) | ||
} | ||
|
||
//set set folder permission on the mount path | ||
chmodCmd := exec.Command("sudo", "chmod", "770", mountPath) | ||
err = chmodCmd.Run() | ||
if err != nil { | ||
return fmt.Errorf("failed set permisions on mount path due to following error: [%s]", err.Error()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. I think that makes it a bit easier and prevents us from doing something wrong to the users system.
cmd/service_linux.go
Outdated
//--------------- command section ends | ||
|
||
func newServiceFile(mountPath string, configPath string, serviceUser string) (string, error) { | ||
serviceTemplate := ` [Unit] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There shouldn't be a space here before [Unit]
cmd/service_linux.go
Outdated
# User service will run as. | ||
User={{.ServiceUser}} | ||
# Path to the location Cloudfuse will mount to. Note this folder must currently exist. | ||
Environment=MountingPoint={{.MountPath}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could simplify this environment section. I only did it this way to make it easy for a user to edit. But if you write it then you could just put the mountPath in the mount and unmount commands directly.
} | ||
} else { | ||
//add group to serviceUser group | ||
usermodCmd := exec.Command("sudo", "usermod", "-aG", configFileGroup.Name, serviceUser) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the user exists, we probably should not modify the group permissions and assume the user has them set in a way to run cloudfuse. And if there is an error we should tell them how to fix that error.
What type of Pull Request is this? (check all applicable)
Describe your changes in brief
This adds the following commands available to the cloudfuse executable:
cloudfuse service install
cloudfuse service uninstall
Checklist
Related Issues