@@ -18,68 +18,58 @@ package install
18
18
19
19
import (
20
20
"errors"
21
- "fmt"
22
21
"os/exec"
23
22
"os/user"
24
- "reflect"
25
- "strings"
23
+ "slices"
26
24
27
25
"github.com/sirupsen/logrus"
28
26
29
- "github.com/k0sproject/k0s/internal/pkg/stringslice"
30
27
"github.com/k0sproject/k0s/internal/pkg/users"
31
28
"github.com/k0sproject/k0s/pkg/apis/k0s/v1beta1"
32
- "github.com/k0sproject/k0s/pkg/config"
33
29
)
34
30
35
- func GetControllerUsers (clusterConfig * v1beta1.ClusterConfig ) []string {
36
- return getUserList (* clusterConfig .Spec .Install .SystemUsers )
37
- }
31
+ // Ensures that all controller users exist and creates any missing users with
32
+ // the given home directory.
33
+ func EnsureControllerUsers (systemUsers * v1beta1.SystemUser , homeDir string ) error {
34
+ var shell string
35
+ var errs []error
36
+ for _ , userName := range getControllerUserNames (systemUsers ) {
37
+ _ , err := users .GetUID (userName )
38
+ if errors .Is (err , user .UnknownUserError (userName )) {
39
+ if shell == "" {
40
+ shell , err = nologinShell ()
41
+ if err != nil {
42
+ // error out early, k0s won't be able to create any users anyways
43
+ errs = append (errs , err )
44
+ break
45
+ }
46
+ }
38
47
39
- // CreateControllerUsers accepts a cluster config, and cfgVars and creates controller users accordingly
40
- func CreateControllerUsers (clusterConfig * v1beta1.ClusterConfig , k0sVars * config.CfgVars ) error {
41
- users := getUserList (* clusterConfig .Spec .Install .SystemUsers )
42
- var messages []string
43
- for _ , v := range users {
44
- if err := EnsureUser (v , k0sVars .DataDir ); err != nil {
45
- messages = append (messages , err .Error ())
48
+ logrus .Infof ("Creating user %q" , userName )
49
+ err = createUser (userName , homeDir , shell )
50
+ }
51
+ if err != nil {
52
+ errs = append (errs , err )
46
53
}
47
54
}
48
- if len (messages ) > 0 {
49
- return fmt .Errorf (strings .Join (messages , "\n " ))
50
- }
51
- return nil
55
+
56
+ return errors .Join (errs ... )
52
57
}
53
58
54
- // CreateControllerUsers accepts a cluster config, and cfgVars and creates controller users accordingly
55
- func DeleteControllerUsers (clusterConfig * v1beta1.ClusterConfig ) error {
56
- cfgUsers := getUserList (* clusterConfig .Spec .Install .SystemUsers )
57
- var messages []string
58
- for _ , v := range cfgUsers {
59
- if _ , err := users .GetUID (v ); err == nil {
60
- logrus .Debugf ("deleting user: %s" , v )
59
+ // Deletes existing controller users.
60
+ func DeleteControllerUsers (systemUsers * v1beta1.SystemUser ) error {
61
+ var errs []error
62
+ for _ , userName := range getControllerUserNames (systemUsers ) {
63
+ if _ , err := users .GetUID (userName ); err == nil {
64
+ logrus .Debugf ("Deleting user %q" , userName )
61
65
62
- if err := deleteUser (v ); err != nil {
63
- messages = append (messages , err . Error () )
66
+ if err := deleteUser (userName ); err != nil {
67
+ errs = append (errs , err )
64
68
}
65
69
}
66
70
}
67
- if len (messages ) > 0 {
68
- // don't fail the command, just notify on errors
69
- return fmt .Errorf (strings .Join (messages , "\n " ))
70
- }
71
- return nil
72
- }
73
71
74
- // EnsureUser checks if a user exists, and creates it, if it doesn't
75
- // TODO: we should also consider modifying the user, if the user exists, but with wrong settings
76
- func EnsureUser (name string , homeDir string ) error {
77
- _ , err := users .GetUID (name )
78
- if errors .Is (err , user .UnknownUserError (name )) {
79
- logrus .Infof ("creating user: %s" , name )
80
- return createUser (name , homeDir )
81
- }
82
- return err
72
+ return errors .Join (errs ... )
83
73
}
84
74
85
75
// nologinShell returns the path to /sbin/nologin, /bin/false or equivalent or an error if neither is available
@@ -93,13 +83,8 @@ func nologinShell() (string, error) {
93
83
}
94
84
95
85
// CreateUser creates a system user with either `adduser` or `useradd` command
96
- func createUser (userName string , homeDir string ) error {
97
- shell , err := nologinShell ()
98
- if err != nil {
99
- return err
100
- }
101
-
102
- _ , err = exec .Command ("useradd" , `--home` , homeDir , `--shell` , shell , `--system` , `--no-create-home` , userName ).Output ()
86
+ func createUser (userName , homeDir , shell string ) error {
87
+ _ , err := exec .Command ("useradd" , `--home` , homeDir , `--shell` , shell , `--system` , `--no-create-home` , userName ).Output ()
103
88
if errors .Is (err , exec .ErrNotFound ) {
104
89
_ , err = exec .Command ("adduser" , `--disabled-password` , `--gecos` , `""` , `--home` , homeDir , `--shell` , shell , `--system` , `--no-create-home` , userName ).Output ()
105
90
}
@@ -115,13 +100,16 @@ func deleteUser(userName string) error {
115
100
return err
116
101
}
117
102
118
- // get user list
119
- func getUserList (sysUsers v1beta1.SystemUser ) []string {
120
- v := reflect .ValueOf (sysUsers )
121
- values := make ([]string , v .NumField ())
122
-
123
- for i := 0 ; i < v .NumField (); i ++ {
124
- values [i ] = v .Field (i ).String ()
103
+ // Returns the controller user names.
104
+ func getControllerUserNames (users * v1beta1.SystemUser ) []string {
105
+ userNames := []string {
106
+ users .Etcd ,
107
+ users .Kine ,
108
+ users .Konnectivity ,
109
+ users .KubeAPIServer ,
110
+ users .KubeScheduler ,
125
111
}
126
- return stringslice .Unique (values )
112
+
113
+ slices .Sort (userNames )
114
+ return slices .Compact (userNames )
127
115
}
0 commit comments