Skip to content

Commit

Permalink
[GraphQL] Generate & Implement RBAC types (#4793)
Browse files Browse the repository at this point in the history
Closes sensu/sensu-enterprise-go#2313
Required by sensu/sensu-enterprise-go#2362

Signed-off-by: James Phillips <[email protected]>
  • Loading branch information
jamesdphillips authored Jul 21, 2022
1 parent f6f6a2c commit 35d0545
Show file tree
Hide file tree
Showing 13 changed files with 1,564 additions and 1,135 deletions.
110 changes: 110 additions & 0 deletions backend/apid/graphql/corev2.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import (
"github.com/sensu/sensu-go/types"
)

//
// CoreV2Pipeline
//

var _ schema.CoreV2PipelineExtensionOverridesFieldResolvers = (*corev2PipelineImpl)(nil)

type corev2PipelineImpl struct {
schema.CoreV2PipelineAliases
}
Expand All @@ -27,3 +33,107 @@ func (*corev2PipelineImpl) IsTypeOf(s interface{}, p graphql.IsTypeOfParams) boo
_, ok := s.(*corev2.Pipeline)
return ok
}

//
// Implement ClusterRoleFieldResolvers
//

var _ schema.CoreV2ClusterRoleExtensionOverridesFieldResolvers = (*clusterRoleImpl)(nil)

type clusterRoleImpl struct {
schema.CoreV2ClusterRoleAliases
}

// ID implements response to request for 'id' field.
func (*clusterRoleImpl) ID(p graphql.ResolveParams) (string, error) {
return globalid.ClusterRoleTranslator.EncodeToString(p.Context, p.Source), nil
}

// ToJSON implements response to request for 'toJSON' field.
func (*clusterRoleImpl) ToJSON(p graphql.ResolveParams) (interface{}, error) {
return types.WrapResource(p.Source.(corev2.Resource)), nil
}

// IsTypeOf is used to determine if a given value is associated with the type
func (*clusterRoleImpl) IsTypeOf(s interface{}, p graphql.IsTypeOfParams) bool {
_, ok := s.(*corev2.ClusterRole)
return ok
}

//
// Implement ClusterRoleBindingFieldResolvers
//

var _ schema.CoreV2ClusterRoleBindingExtensionOverridesFieldResolvers = (*clusterRoleBindingImpl)(nil)

type clusterRoleBindingImpl struct {
schema.CoreV2ClusterRoleBindingAliases
}

// ID implements response to request for 'id' field.
func (*clusterRoleBindingImpl) ID(p graphql.ResolveParams) (string, error) {
return globalid.ClusterRoleBindingTranslator.EncodeToString(p.Context, p.Source), nil
}

// ToJSON implements response to request for 'toJSON' field.
func (*clusterRoleBindingImpl) ToJSON(p graphql.ResolveParams) (interface{}, error) {
return types.WrapResource(p.Source.(corev2.Resource)), nil
}

// IsTypeOf is used to determine if a given value is associated with the type
func (*clusterRoleBindingImpl) IsTypeOf(s interface{}, p graphql.IsTypeOfParams) bool {
_, ok := s.(*corev2.ClusterRoleBinding)
return ok
}

//
// Implement RoleFieldResolvers
//

var _ schema.CoreV2RoleExtensionOverridesFieldResolvers = (*roleImpl)(nil)

type roleImpl struct {
schema.CoreV2RoleAliases
}

// ID implements response to request for 'id' field.
func (*roleImpl) ID(p graphql.ResolveParams) (string, error) {
return globalid.RoleTranslator.EncodeToString(p.Context, p.Source), nil
}

// ToJSON implements response to request for 'toJSON' field.
func (*roleImpl) ToJSON(p graphql.ResolveParams) (interface{}, error) {
return types.WrapResource(p.Source.(corev2.Resource)), nil
}

// IsTypeOf is used to determine if a given value is associated with the type
func (*roleImpl) IsTypeOf(s interface{}, p graphql.IsTypeOfParams) bool {
_, ok := s.(*corev2.Role)
return ok
}

//
// Implement RoleBindingFieldResolvers
//

var _ schema.CoreV2RoleBindingExtensionOverridesFieldResolvers = (*roleBindingImpl)(nil)

type roleBindingImpl struct {
schema.CoreV2RoleBindingAliases
}

// ID implements response to request for 'id' field.
func (*roleBindingImpl) ID(p graphql.ResolveParams) (string, error) {
return globalid.RoleBindingTranslator.EncodeToString(p.Context, p.Source), nil
}

// ToJSON implements response to request for 'toJSON' field.
func (*roleBindingImpl) ToJSON(p graphql.ResolveParams) (interface{}, error) {
return types.WrapResource(p.Source.(corev2.Resource)), nil
}

// IsTypeOf is used to determine if a given value is associated with the type
func (*roleBindingImpl) IsTypeOf(s interface{}, p graphql.IsTypeOfParams) bool {
_, ok := s.(*corev2.RoleBinding)
return ok
}
178 changes: 147 additions & 31 deletions backend/apid/graphql/corev2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package graphql

import (
"context"
"fmt"
"reflect"
"testing"

Expand All @@ -10,24 +11,56 @@ import (
"github.com/sensu/sensu-go/types"
)

func Test_corev2PipelineImpl_ID(t *testing.T) {
func Test_corev2_ID(t *testing.T) {
tests := []struct {
name string
in *corev2.Pipeline
name string
resolver interface {
ID(p graphql.ResolveParams) (string, error)
}
in interface{}
want string
wantErr bool
}{
{
name: "default",
in: corev2.FixturePipeline("test", "default"),
want: "srn:corev2/pipeline:default:test",
wantErr: false,
name: "default",
resolver: &corev2PipelineImpl{},
in: corev2.FixturePipeline("test", "default"),
want: "srn:corev2/pipeline:default:test",
wantErr: false,
},
{
name: "role",
resolver: &roleImpl{},
in: corev2.FixtureRole("test", "default"),
want: "srn:roles:default:test",
wantErr: false,
},
{
name: "role_binding",
resolver: &roleBindingImpl{},
in: corev2.FixtureRoleBinding("test", "default"),
want: "srn:rolebindings:default:test",
wantErr: false,
},
{
name: "cluster_role",
resolver: &clusterRoleImpl{},
in: corev2.FixtureClusterRole("test"),
want: "srn:clusterroles:test",
wantErr: false,
},
{
name: "cluster_role_binding",
resolver: &clusterRoleBindingImpl{},
in: corev2.FixtureClusterRoleBinding("test"),
want: "srn:clusterrolebindings:test",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tr := &corev2PipelineImpl{}
got, err := tr.ID(graphql.ResolveParams{Context: context.Background(), Source: tt.in})
t.Run(fmt.Sprintf("%T/%s", tt.resolver, tt.name), func(t *testing.T) {
params := graphql.ResolveParams{Context: context.Background(), Source: tt.in}
got, err := tt.resolver.ID(params)
if (err != nil) != tt.wantErr {
t.Errorf("corev2PipelineImpl.ID() error = %v, wantErr %v", err, tt.wantErr)
return
Expand All @@ -39,24 +72,55 @@ func Test_corev2PipelineImpl_ID(t *testing.T) {
}
}

func Test_corev2PipelineImp_ToJSON(t *testing.T) {
func Test_corev2_ToJSON(t *testing.T) {
tests := []struct {
name string
in *corev2.Pipeline
name string
resolver interface {
ToJSON(p graphql.ResolveParams) (interface{}, error)
}
in interface{}
want interface{}
wantErr bool
}{
{
name: "default",
in: corev2.FixturePipeline("name", "default"),
want: types.WrapResource(corev2.FixturePipeline("name", "default")),
wantErr: false,
name: "default",
resolver: &corev2PipelineImpl{},
in: corev2.FixturePipeline("name", "default"),
want: types.WrapResource(corev2.FixturePipeline("name", "default")),
wantErr: false,
},
{
name: "default",
resolver: &roleImpl{},
in: corev2.FixtureRole("name", "default"),
want: types.WrapResource(corev2.FixtureRole("name", "default")),
wantErr: false,
},
{
name: "default",
resolver: &roleBindingImpl{},
in: corev2.FixtureRoleBinding("name", "default"),
want: types.WrapResource(corev2.FixtureRoleBinding("name", "default")),
wantErr: false,
},
{
name: "default",
resolver: &clusterRoleImpl{},
in: corev2.FixtureClusterRole("name"),
want: types.WrapResource(corev2.FixtureClusterRole("name")),
wantErr: false,
},
{
name: "default",
resolver: &clusterRoleBindingImpl{},
in: corev2.FixtureClusterRoleBinding("name"),
want: types.WrapResource(corev2.FixtureClusterRoleBinding("name")),
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tr := &corev2PipelineImpl{}
got, err := tr.ToJSON(graphql.ResolveParams{Context: context.Background(), Source: tt.in})
t.Run(fmt.Sprintf("%T/%s", tt.resolver, tt.name), func(t *testing.T) {
got, err := tt.resolver.ToJSON(graphql.ResolveParams{Context: context.Background(), Source: tt.in})
if (err != nil) != tt.wantErr {
t.Errorf("corev2PipelineImpl.ToJSON() error = %v, wantErr %v", err, tt.wantErr)
return
Expand All @@ -68,27 +132,79 @@ func Test_corev2PipelineImp_ToJSON(t *testing.T) {
}
}

func Test_corev2PipelineImp_IsTypeOf(t *testing.T) {
func Test_corev2types_IsTypeOf(t *testing.T) {
tests := []struct {
name string
name string
resolver interface {
IsTypeOf(s interface{}, p graphql.IsTypeOfParams) bool
}
in interface{}
want bool
}{
{
name: "match",
in: corev2.FixturePipeline("name", "default"),
want: true,
name: "match",
resolver: &corev2PipelineImpl{},
in: corev2.FixturePipeline("name", "default"),
want: true,
},
{
name: "no match",
resolver: &corev2PipelineImpl{},
in: corev2.FixtureEntity("name"),
want: false,
},
{
name: "match",
resolver: &roleImpl{},
in: corev2.FixtureRole("name", "default"),
want: true,
},
{
name: "no match",
resolver: &roleImpl{},
in: corev2.FixtureEntity("name"),
want: false,
},
{
name: "match",
resolver: &roleBindingImpl{},
in: corev2.FixtureRoleBinding("name", "default"),
want: true,
},
{
name: "no match",
resolver: &roleBindingImpl{},
in: corev2.FixtureEntity("name"),
want: false,
},
{
name: "match",
resolver: &clusterRoleImpl{},
in: corev2.FixtureClusterRole("name"),
want: true,
},
{
name: "no match",
resolver: &clusterRoleImpl{},
in: corev2.FixtureEntity("name"),
want: false,
},
{
name: "match",
resolver: &clusterRoleBindingImpl{},
in: corev2.FixtureClusterRoleBinding("name"),
want: true,
},
{
name: "no match",
in: corev2.FixtureEntity("name"),
want: false,
name: "no match",
resolver: &clusterRoleBindingImpl{},
in: corev2.FixtureEntity("name"),
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tr := &corev2PipelineImpl{}
got := tr.IsTypeOf(tt.in, graphql.IsTypeOfParams{Context: context.Background()})
t.Run(fmt.Sprintf("%T/%s", tt.resolver, tt.name), func(t *testing.T) {
got := tt.resolver.IsTypeOf(tt.in, graphql.IsTypeOfParams{Context: context.Background()})
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("corev2PipelineImpl.ToJSON() = %v, want %v", got, tt.want)
}
Expand Down
8 changes: 4 additions & 4 deletions backend/apid/graphql/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func registerMutatorNodeResolver(register relay.NodeRegister, client GenericClie

func registerClusterRoleNodeResolver(register relay.NodeRegister, client RBACClient) {
register.RegisterResolver(relay.NodeResolver{
ObjectType: schema.ClusterRoleType,
ObjectType: schema.CoreV2ClusterRoleType,
Translator: globalid.ClusterRoleTranslator,
Resolve: func(p relay.NodeResolverParams) (interface{}, error) {
ctx := setContextFromComponents(p.Context, p.IDComponents)
Expand All @@ -133,7 +133,7 @@ func registerClusterRoleNodeResolver(register relay.NodeRegister, client RBACCli

func registerClusterRoleBindingNodeResolver(register relay.NodeRegister, client RBACClient) {
register.RegisterResolver(relay.NodeResolver{
ObjectType: schema.ClusterRoleBindingType,
ObjectType: schema.CoreV2ClusterRoleBindingType,
Translator: globalid.ClusterRoleBindingTranslator,
Resolve: func(p relay.NodeResolverParams) (interface{}, error) {
ctx := setContextFromComponents(p.Context, p.IDComponents)
Expand All @@ -147,7 +147,7 @@ func registerClusterRoleBindingNodeResolver(register relay.NodeRegister, client

func registerRoleNodeResolver(register relay.NodeRegister, client RBACClient) {
register.RegisterResolver(relay.NodeResolver{
ObjectType: schema.RoleType,
ObjectType: schema.CoreV2RoleType,
Translator: globalid.RoleTranslator,
Resolve: func(p relay.NodeResolverParams) (interface{}, error) {
ctx := setContextFromComponents(p.Context, p.IDComponents)
Expand All @@ -161,7 +161,7 @@ func registerRoleNodeResolver(register relay.NodeRegister, client RBACClient) {

func registerRoleBindingNodeResolver(register relay.NodeRegister, client RBACClient) {
register.RegisterResolver(relay.NodeResolver{
ObjectType: schema.RoleBindingType,
ObjectType: schema.CoreV2RoleBindingType,
Translator: globalid.RoleBindingTranslator,
Resolve: func(p relay.NodeResolverParams) (interface{}, error) {
ctx := setContextFromComponents(p.Context, p.IDComponents)
Expand Down
Loading

0 comments on commit 35d0545

Please sign in to comment.