~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/utils/username.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2015 Canonical Ltd.
 
2
// Licensed under the LGPLv3, see LICENCE file for details.
 
3
 
 
4
package utils
 
5
 
 
6
import (
 
7
        "os"
 
8
        "os/user"
 
9
 
 
10
        "github.com/juju/errors"
 
11
)
 
12
 
 
13
// ResolveSudo returns the original username if sudo was used. The
 
14
// original username is extracted from the OS environment.
 
15
func ResolveSudo(username string) string {
 
16
        return resolveSudo(username, os.Getenv)
 
17
}
 
18
 
 
19
func resolveSudo(username string, getenvFunc func(string) string) string {
 
20
        if username != "root" {
 
21
                return username
 
22
        }
 
23
        // sudo was probably called, get the original user.
 
24
        if username := getenvFunc("SUDO_USER"); username != "" {
 
25
                return username
 
26
        }
 
27
        return username
 
28
}
 
29
 
 
30
// EnvUsername returns the username from the OS environment.
 
31
func EnvUsername() (string, error) {
 
32
        return os.Getenv("USER"), nil
 
33
}
 
34
 
 
35
// OSUsername returns the username of the current OS user (based on UID).
 
36
func OSUsername() (string, error) {
 
37
        u, err := user.Current()
 
38
        if err != nil {
 
39
                return "", errors.Trace(err)
 
40
        }
 
41
        return u.Username, nil
 
42
}
 
43
 
 
44
// ResolveUsername returns the username determined by the provided
 
45
// functions. The functions are tried in the same order in which they
 
46
// were passed in. An error returned from any of them is immediately
 
47
// returned. If an empty string is returned then that signals that the
 
48
// function did not find the username and the next function is tried.
 
49
// Once a username is found, the provided resolveSudo func (if any) is
 
50
// called with that username and the result is returned. If no username
 
51
// is found then errors.NotFound is returned.
 
52
func ResolveUsername(resolveSudo func(string) string, usernameFuncs ...func() (string, error)) (string, error) {
 
53
        for _, usernameFunc := range usernameFuncs {
 
54
                username, err := usernameFunc()
 
55
                if err != nil {
 
56
                        return "", errors.Trace(err)
 
57
                }
 
58
                if username != "" {
 
59
                        if resolveSudo != nil {
 
60
                                if original := resolveSudo(username); original != "" {
 
61
                                        username = original
 
62
                                }
 
63
                        }
 
64
                        return username, nil
 
65
                }
 
66
        }
 
67
        return "", errors.NotFoundf("username")
 
68
}
 
69
 
 
70
// LocalUsername determines the current username on the local host.
 
71
func LocalUsername() (string, error) {
 
72
        username, err := ResolveUsername(ResolveSudo, EnvUsername, OSUsername)
 
73
        if err != nil {
 
74
                return "", errors.Annotatef(err, "cannot get current user from the environment: %v", os.Environ())
 
75
        }
 
76
        return username, nil
 
77
}