add interface support

This commit is contained in:
Sasha Klizhentas 2016-12-09 17:31:05 -08:00
parent 0adebbcec6
commit 0f4db522b9
6 changed files with 123 additions and 33 deletions

View file

@ -360,7 +360,7 @@ func (s *APIServer) upsertUser(w http.ResponseWriter, r *http.Request, p httprou
if err := httplib.ReadJSON(r, &req); err != nil {
return nil, trace.Wrap(err)
}
user, err := services.GetUserUnmarshaler()(req.User)
user, err := services.GetUserMarshaler().UnmarshalUser(req.User)
if err != nil {
return nil, trace.Wrap(err)
}
@ -668,7 +668,7 @@ func (s *APIServer) createSignupToken(w http.ResponseWriter, r *http.Request, p
if err := httplib.ReadJSON(r, &req); err != nil {
return nil, trace.Wrap(err)
}
user, err := services.GetUserUnmarshaler()(req.User)
user, err := services.GetUserMarshaler().UnmarshalUser(req.User)
if err != nil {
return nil, trace.Wrap(err)
}

View file

@ -511,7 +511,7 @@ func (c *Client) GetUser(name string) (services.User, error) {
if err != nil {
return nil, trace.Wrap(err)
}
user, err := services.GetUserUnmarshaler()(out.Bytes())
user, err := services.GetUserMarshaler().UnmarshalUser(out.Bytes())
if err != nil {
return nil, trace.Wrap(err)
}
@ -530,7 +530,7 @@ func (c *Client) GetUsers() ([]services.User, error) {
}
users := make([]services.User, len(items))
for i, userBytes := range items {
user, err := services.GetUserUnmarshaler()(userBytes)
user, err := services.GetUserMarshaler().UnmarshalUser(userBytes)
if err != nil {
return nil, trace.Wrap(err)
}

View file

@ -404,26 +404,33 @@ func (u Users) Swap(i, j int) {
}
var mtx sync.Mutex
var unmarshaler UserUnmarshaler
var userMarshaler UserMarshaler = &TeleportUserMarshaler{}
func SetUserUnmarshaler(u UserUnmarshaler) {
func SetUserMarshaler(u UserMarshaler) {
mtx.Lock()
defer mtx.Unlock()
unmarshaler = u
userMarshaler = u
}
func GetUserUnmarshaler() UserUnmarshaler {
func GetUserMarshaler() UserMarshaler {
mtx.Lock()
defer mtx.Unlock()
if unmarshaler == nil {
return TeleportUserUnmarshaler
}
return unmarshaler
return userMarshaler
}
type UserUnmarshaler func(bytes []byte) (User, error)
// UserMarshaler implements marshal/unmarshal of User implementations
// mostly adds support for extended versions
type UserMarshaler interface {
// UnmarshalUser from binary representation
UnmarshalUser(bytes []byte) (User, error)
// MarshalUser to binary representation
MarshalUser(u User) ([]byte, error)
}
func TeleportUserUnmarshaler(bytes []byte) (User, error) {
type TeleportUserMarshaler struct{}
// UnmarshalUser unmarshals user from JSON
func (*TeleportUserMarshaler) UnmarshalUser(bytes []byte) (User, error) {
var u *TeleportUser
err := json.Unmarshal(bytes, &u)
if err != nil {
@ -431,3 +438,8 @@ func TeleportUserUnmarshaler(bytes []byte) (User, error) {
}
return u, nil
}
// MarshalUser marshalls user into JSON
func (*TeleportUserMarshaler) MarshalUser(u User) ([]byte, error) {
return json.Marshal(u)
}

View file

@ -49,6 +49,22 @@ const (
V1 = "v1"
)
// Role contains a set of permissions or settings
type Role interface {
// GetMetadata returns role metadata
GetMetadata() Metadata
// GetMaxSessionTTL is a maximum SSH or Web session TTL
GetMaxSessionTTL() Duration
// GetLogins returns a list of linux logins allowed for this role
GetLogins() []string
// GetNodeLabels returns a list of matchign nodes this role has access to
GetNodeLabels() map[string]string
// GetNamespaces returns a list of namespaces this role has access to
GetNamespaces() []string
// GetResources returns access to resources
GetResources() map[string][]string
}
// Metadata is resource metadata
type Metadata struct {
// Name is an object name
@ -73,6 +89,36 @@ type RoleResource struct {
Spec RoleSpec `json:"spec"`
}
// GetMetadata returns role metadata
func (r *RoleResource) GetMetadata() Metadata {
return r.Metadata
}
// GetMaxSessionTTL is a maximum SSH or Web session TTL
func (r *RoleResource) GetMaxSessionTTL() Duration {
return r.Spec.MaxSessionTTL
}
// GetLogins returns a list of linux logins allowed for this role
func (r *RoleResource) GetLogins() []string {
return r.Spec.Logins
}
// GetNodeLabels returns a list of matchign nodes this role has access to
func (r *RoleResource) GetNodeLabels() map[string]string {
return r.Spec.NodeLabels
}
// GetNamespaces returns a list of namespaces this role has access to
func (r *RoleResource) GetNamespaces() []string {
return r.Spec.Namespaces
}
// GetResources returns access to resources
func (r *RoleResource) GetResources() map[string][]string {
return r.Spec.Resources
}
// RoleSpec is role specification
type RoleSpec struct {
// MaxSessionTTL is a maximum SSH or Web session TTL
@ -115,19 +161,6 @@ func (d *Duration) UnmarshalJSON(data []byte) error {
return nil
}
// UnmarshalRole unmarshals role from JSON or YAML,
// sets defaults and checks the schema
func UnmarshalRole(data []byte) (*RoleResource, error) {
if len(data) == 0 {
return nil, trace.BadParameter("empty input")
}
var role RoleResource
if err := utils.UnmarshalWithSchema(RoleSchema, &role, data); err != nil {
return nil, trace.BadParameter(err.Error())
}
return &role, nil
}
const MetadataSchema = `{
"type": "object",
"additionalProperties": false,
@ -209,3 +242,51 @@ const NodeSelectorSchema = `{
}
}
}`
// UnmarshalRoleResource unmarshals role from JSON or YAML,
// sets defaults and checks the schema
func UnmarshalRoleResource(data []byte) (*RoleResource, error) {
if len(data) == 0 {
return nil, trace.BadParameter("empty input")
}
var role RoleResource
if err := utils.UnmarshalWithSchema(RoleSchema, &role, data); err != nil {
return nil, trace.BadParameter(err.Error())
}
return &role, nil
}
var roleMarshaler RoleMarshaler = &TeleportRoleMarshaler{}
func SetRoleMarshaler(u RoleMarshaler) {
mtx.Lock()
defer mtx.Unlock()
roleMarshaler = u
}
func GetRoleMarshaler() RoleMarshaler {
mtx.Lock()
defer mtx.Unlock()
return roleMarshaler
}
// RoleMarshaler implements marshal/unmarshal of Role implementations
// mostly adds support for extended versions
type RoleMarshaler interface {
// UnmarshalRole from binary representation
UnmarshalRole(bytes []byte) (Role, error)
// MarshalRole to binary representation
MarshalRole(u Role) ([]byte, error)
}
type TeleportRoleMarshaler struct{}
// UnmarshalRole unmarshals role from JSON
func (*TeleportRoleMarshaler) UnmarshalRole(bytes []byte) (Role, error) {
return UnmarshalRoleResource(bytes)
}
// MarshalRole marshalls role into JSON
func (*TeleportRoleMarshaler) MarshalRole(u Role) ([]byte, error) {
return json.Marshal(u)
}

View file

@ -18,7 +18,6 @@ package services
import (
"encoding/json"
"fmt"
"testing"
"time"
@ -121,7 +120,7 @@ spec:
}
for i, tc := range testCases {
comment := Commentf("test case %v", i)
role, err := UnmarshalRole([]byte(tc.in))
role, err := UnmarshalRoleResource([]byte(tc.in))
if tc.error != nil {
c.Assert(err, NotNil, comment)
} else {
@ -131,9 +130,7 @@ spec:
out, err := json.Marshal(*role)
c.Assert(err, IsNil, comment)
fmt.Printf("out: %v\n", string(out))
role2, err := UnmarshalRole(out)
role2, err := UnmarshalRoleResource(out)
c.Assert(err, IsNil, comment)
c.Assert(*role2, DeepEquals, tc.role, comment)
}

View file

@ -444,7 +444,7 @@ type createSessionResponseRaw struct {
}
func (r createSessionResponseRaw) response() (*CreateSessionResponse, error) {
user, err := services.GetUserUnmarshaler()(r.User)
user, err := services.GetUserMarshaler().UnmarshalUser(r.User)
if err != nil {
return nil, trace.Wrap(err)
}