forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
etcd.go
115 lines (93 loc) · 3.36 KB
/
etcd.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package etcd
import (
"errors"
"fmt"
etcderrs "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/openshift/origin/pkg/user"
"github.com/openshift/origin/pkg/user/api"
)
// Etcd implements UserIdentityMapping backed by etcd.
type Etcd struct {
tools.EtcdHelper
initializer user.Initializer
}
// New returns a new Etcd.
func New(helper tools.EtcdHelper, initializer user.Initializer) *Etcd {
return &Etcd{
EtcdHelper: helper,
initializer: initializer,
}
}
var errExists = errors.New("the mapping already exists")
func makeUserKey(id string) string {
return "/userIdentityMappings/" + id
}
func (r *Etcd) GetUser(name string) (user *api.User, err error) {
mapping := &api.UserIdentityMapping{}
err = r.ExtractObj(makeUserKey(name), mapping, false)
err = etcderrs.InterpretGetError(err, "User", name)
user = &mapping.User
return
}
func (r *Etcd) GetUserIdentityMapping(name string) (mapping *api.UserIdentityMapping, err error) {
mapping = &api.UserIdentityMapping{}
err = r.ExtractObj(makeUserKey(name), mapping, false)
err = etcderrs.InterpretGetError(err, "UserIdentityMapping", name)
return
}
// CreateOrUpdateUserIdentityMapping implements useridentitymapping.Registry
func (r *Etcd) CreateOrUpdateUserIdentityMapping(mapping *api.UserIdentityMapping) (*api.UserIdentityMapping, bool, error) {
// Create Identity.Name by combining Provider and UserName
name := fmt.Sprintf("%s:%s", mapping.Identity.Provider, mapping.Identity.UserName)
key := makeUserKey(name)
// track the object we set into etcd to return
var found *api.UserIdentityMapping
var created bool
err := r.AtomicUpdate(key, &api.UserIdentityMapping{}, true, func(in runtime.Object) (runtime.Object, error) {
existing := *in.(*api.UserIdentityMapping)
// did not previously exist
if existing.Name == "" {
now := util.Now()
// TODO: move these initializations the rest layer once we stop using the registry directly
existing.Name = name
existing.UID = util.NewUUID()
existing.CreationTimestamp = now
existing.Identity = mapping.Identity
identityuid := util.NewUUID()
existing.Identity.Name = name
existing.Identity.UID = identityuid
existing.Identity.CreationTimestamp = now
useruid := util.NewUUID()
existing.User.Name = name
existing.User.UID = useruid
existing.User.CreationTimestamp = now
if err := r.initializer.InitializeUser(&existing.Identity, &existing.User); err != nil {
return in, err
}
// set these again to prevent bad initialization from messing up data
existing.Identity.Name = name
existing.Identity.UID = identityuid
existing.Identity.CreationTimestamp = now
existing.User.Name = name
existing.User.UID = useruid
existing.User.CreationTimestamp = now
found = &existing
created = true
return &existing, nil
}
if existing.User.Name != name {
return in, fmt.Errorf("the provided user name does not match the existing mapping %s", existing.User.Name)
}
found = &existing
// TODO: should update identity based on new info as well.
return in, errExists
})
if err != nil && err != errExists {
err = etcderrs.InterpretCreateError(err, "UserIdentityMapping", name)
return nil, false, err
}
return found, created, nil
}