Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Powerflex pre-approved GUIDs #208

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions cmd/karavictl/cmd/tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import (
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/protobuf/encoding/protojson"
ashleyvjoy marked this conversation as resolved.
Show resolved Hide resolved
"google.golang.org/protobuf/reflect/protoreflect"
)

// NewTenantCmd creates a new tenant command
Expand All @@ -54,6 +56,7 @@ func NewTenantCmd() *cobra.Command {
tenantCmd.AddCommand(NewTenantGetCmd())
tenantCmd.AddCommand(NewTenantListCmd())
tenantCmd.AddCommand(NewTenantRevokeCmd())
tenantCmd.AddCommand(NewTenantUpdateCmd())
return tenantCmd
}

Expand Down Expand Up @@ -121,3 +124,11 @@ func jsonOutput(w io.Writer, v interface{}) error {
}
return nil
}

// jsonOutput() omits boolean flag on false value while encoding
func jsonOutputEmitEmpty(w io.Writer, m protoreflect.ProtoMessage) error {
enc := protojson.MarshalOptions{Multiline: true, EmitUnpopulated: true, Indent: ""}
data := enc.Format(m)
fmt.Fprintln(w, data)
return nil
}
11 changes: 9 additions & 2 deletions cmd/karavictl/cmd/tenant_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,24 @@ func NewTenantCreateCmd() *cobra.Command {
reportErrorAndExit(JSONOutput, cmd.ErrOrStderr(), errors.New("empty name not allowed"))
}

approveSdc, err := cmd.Flags().GetBool("approvesdc")
if err != nil {
reportErrorAndExit(JSONOutput, cmd.ErrOrStderr(), err)
}

_, err = tenantClient.CreateTenant(context.Background(), &pb.CreateTenantRequest{
Tenant: &pb.Tenant{
Name: name,
Name: name,
Approvesdc: approveSdc,
},
})
if err != nil {
reportErrorAndExit(JSONOutput, cmd.ErrOrStderr(), err)
reportErrorAndExit(jsonOutput, cmd.ErrOrStderr(), err)
}
},
}

tenantCreateCmd.Flags().StringP("name", "n", "", "Tenant name")
tenantCreateCmd.Flags().Bool("approvesdc", true, "To allow/deny SDC approval requests")
return tenantCreateCmd
}
21 changes: 21 additions & 0 deletions cmd/karavictl/cmd/tenant_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,25 @@ func TestTenantCreate(t *testing.T) {
t.Errorf("got err %q, want %q", gotErr.ErrorMsg, wantErrMsg)
}
})
t.Run("it requests creation of a tenant with setting approvesdc flag explicitly", func(t *testing.T) {
defer afterFn()
CreateTenantServiceClient = func(_ string, _ bool) (pb.TenantServiceClient, io.Closer, error) {
return &fakeTenantServiceClient{}, ioutil.NopCloser(nil), nil
}
JSONOutput = func(w io.Writer, _ interface{}) error {
return nil
}
osExit = func(code int) {
}
var gotOutput bytes.Buffer

cmd := NewRootCmd()
cmd.SetOutput(&gotOutput)
cmd.SetArgs([]string{"tenant", "create", "-n", "testname", "--approvesdc", "true"})
cmd.Execute()

if len(gotOutput.Bytes()) != 0 {
t.Errorf("expected zero output but got %q", string(gotOutput.Bytes()))
}
})
}
6 changes: 3 additions & 3 deletions cmd/karavictl/cmd/tenant_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ func NewTenantGetCmd() *cobra.Command {
Name: name,
})
if err != nil {
reportErrorAndExit(JSONOutput, cmd.ErrOrStderr(), err)
reportErrorAndExit(jsonOutput, cmd.ErrOrStderr(), err)
}

err = JSONOutput(cmd.OutOrStdout(), &t)
err = jsonOutputEmitEmpty(cmd.ErrOrStderr(), t)
if err != nil {
reportErrorAndExit(JSONOutput, cmd.ErrOrStderr(), err)
reportErrorAndExit(jsonOutput, cmd.ErrOrStderr(), err)
}
},
}
Expand Down
10 changes: 10 additions & 0 deletions cmd/karavictl/cmd/tenant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
type fakeTenantServiceClient struct {
pb.TenantServiceClient
CreateTenantFn func(context.Context, *pb.CreateTenantRequest, ...grpc.CallOption) (*pb.Tenant, error)
UpdateTenantFn func(context.Context, *pb.UpdateTenantRequest, ...grpc.CallOption) (*pb.Tenant, error)
GetTenantFn func(context.Context, *pb.GetTenantRequest, ...grpc.CallOption) (*pb.Tenant, error)
DeleteTenantFn func(context.Context, *pb.DeleteTenantRequest, ...grpc.CallOption) (*pb.DeleteTenantResponse, error)
ListTenantFn func(context.Context, *pb.ListTenantRequest, ...grpc.CallOption) (*pb.ListTenantResponse, error)
Expand All @@ -40,6 +41,15 @@ func (f *fakeTenantServiceClient) CreateTenant(ctx context.Context, in *pb.Creat
}, nil
}

func (f *fakeTenantServiceClient) UpdateTenant(ctx context.Context, in *pb.UpdateTenantRequest, opts ...grpc.CallOption) (*pb.Tenant, error) {
if f.UpdateTenantFn != nil {
return f.UpdateTenantFn(ctx, in, opts...)
}
return &pb.Tenant{
Name: "testname",
}, nil
}

func (f *fakeTenantServiceClient) GetTenant(ctx context.Context, in *pb.GetTenantRequest, opts ...grpc.CallOption) (*pb.Tenant, error) {
if f.GetTenantFn != nil {
return f.GetTenantFn(ctx, in, opts...)
Expand Down
76 changes: 76 additions & 0 deletions cmd/karavictl/cmd/tenant_update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright © 2023 Dell Inc., or its subsidiaries. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd
ashleyvjoy marked this conversation as resolved.
Show resolved Hide resolved

import (
"context"
"errors"
"karavi-authorization/pb"
"strings"

"github.com/spf13/cobra"
)

// NewTenantUpdateCmd creates a new update command for tenant
func NewTenantUpdateCmd() *cobra.Command {
tenantUpdateCmd := &cobra.Command{
Use: "update",
TraverseChildren: true,
Short: "Update a tenant resource within CSM Authorization",
Long: `Updates a tenant resource within CSM Authorization`,
Run: func(cmd *cobra.Command, args []string) {
addr, err := cmd.Flags().GetString("addr")
if err != nil {
reportErrorAndExit(JSONOutput, cmd.ErrOrStderr(), err)
}

insecure, err := cmd.Flags().GetBool("insecure")
if err != nil {
reportErrorAndExit(JSONOutput, cmd.ErrOrStderr(), err)
}

tenantClient, conn, err := CreateTenantServiceClient(addr, insecure)
if err != nil {
reportErrorAndExit(JSONOutput, cmd.ErrOrStderr(), err)
}
defer conn.Close()

name, err := cmd.Flags().GetString("name")
if err != nil {
reportErrorAndExit(JSONOutput, cmd.ErrOrStderr(), err)
}
if strings.TrimSpace(name) == "" {
reportErrorAndExit(JSONOutput, cmd.ErrOrStderr(), errors.New("empty name not allowed"))
}

approveSdc, err := cmd.Flags().GetBool("approvesdc")
if err != nil {
reportErrorAndExit(JSONOutput, cmd.ErrOrStderr(), err)
}

_, err = tenantClient.UpdateTenant(context.Background(), &pb.UpdateTenantRequest{
TenantName: name,
Approvesdc: approveSdc,
})
if err != nil {
reportErrorAndExit(JSONOutput, cmd.ErrOrStderr(), err)
}
},
}

tenantUpdateCmd.Flags().StringP("name", "n", "", "Tenant name")
tenantUpdateCmd.Flags().Bool("approvesdc", true, "To allow/deny SDC approval requests")
return tenantUpdateCmd
}
165 changes: 165 additions & 0 deletions cmd/karavictl/cmd/tenant_update_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// Copyright © 2023 Dell Inc., or its subsidiaries. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd
ashleyvjoy marked this conversation as resolved.
Show resolved Hide resolved

import (
"bytes"
"context"
"encoding/json"
"errors"
"io"
"io/ioutil"
"karavi-authorization/pb"
"os"
"testing"

"google.golang.org/grpc"
)

func TestTenantUpdate(t *testing.T) {
afterFn := func() {
CreateTenantServiceClient = createTenantServiceClient
JSONOutput = jsonOutput
osExit = os.Exit
}

t.Run("it requests updation of a tenant", func(t *testing.T) {
defer afterFn()
CreateTenantServiceClient = func(_ string, _ bool) (pb.TenantServiceClient, io.Closer, error) {
return &fakeTenantServiceClient{}, ioutil.NopCloser(nil), nil
}
JSONOutput = func(w io.Writer, _ interface{}) error {
return nil
}
osExit = func(code int) {
}
var gotOutput bytes.Buffer

cmd := NewRootCmd()
cmd.SetOutput(&gotOutput)
cmd.SetArgs([]string{"tenant", "update", "-n", "testname", "--approvesdc", "true"})
cmd.Execute()

if len(gotOutput.Bytes()) != 0 {
t.Errorf("expected zero output but got %q", string(gotOutput.Bytes()))
}
})
t.Run("it requires a valid tenant server connection", func(t *testing.T) {
defer afterFn()
CreateTenantServiceClient = func(_ string, _ bool) (pb.TenantServiceClient, io.Closer, error) {
return nil, ioutil.NopCloser(nil), errors.New("test error")
}
var gotCode int
done := make(chan struct{})
osExit = func(code int) {
gotCode = code
done <- struct{}{}
done <- struct{}{} // we can't let this function return
}
var gotOutput bytes.Buffer

cmd := NewRootCmd()
cmd.SetErr(&gotOutput)
cmd.SetArgs([]string{"tenant", "update", "-n", "testname", "--approvesdc", "true"})
go cmd.Execute()
<-done

wantCode := 1
if gotCode != wantCode {
t.Errorf("got exit code %d, want %d", gotCode, wantCode)
}
var gotErr CommandError
if err := json.NewDecoder(&gotOutput).Decode(&gotErr); err != nil {
t.Fatal(err)
}
wantErrMsg := "test error"
if gotErr.ErrorMsg != wantErrMsg {
t.Errorf("got err %q, want %q", gotErr.ErrorMsg, wantErrMsg)
}
})
t.Run("it requires a valid name argument", func(t *testing.T) {
defer afterFn()
CreateTenantServiceClient = func(_ string, _ bool) (pb.TenantServiceClient, io.Closer, error) {
return &fakeTenantServiceClient{}, ioutil.NopCloser(nil), nil
}
var gotCode int
done := make(chan struct{})
osExit = func(code int) {
gotCode = code
done <- struct{}{}
done <- struct{}{} // we can't let this function return
}

var gotOutput bytes.Buffer

rootCmd := NewRootCmd()
rootCmd.SetErr(&gotOutput)
rootCmd.SetArgs([]string{"tenant", "update"})

go rootCmd.Execute()
<-done

wantCode := 1
if gotCode != wantCode {
t.Errorf("got exit code %d, want %d", gotCode, wantCode)
}
var gotErr CommandError
if err := json.NewDecoder(&gotOutput).Decode(&gotErr); err != nil {
t.Fatal(err)
}
wantErrMsg := "empty name not allowed"
if gotErr.ErrorMsg != wantErrMsg {
t.Errorf("got err %q, want %q", gotErr.ErrorMsg, wantErrMsg)
}
})
t.Run("it handles server errors", func(t *testing.T) {
defer afterFn()
CreateTenantServiceClient = func(_ string, _ bool) (pb.TenantServiceClient, io.Closer, error) {
return &fakeTenantServiceClient{
UpdateTenantFn: func(_ context.Context, _ *pb.UpdateTenantRequest, _ ...grpc.CallOption) (*pb.Tenant, error) {
return nil, errors.New("test error")
},
}, ioutil.NopCloser(nil), nil
}
var gotCode int
done := make(chan struct{})
osExit = func(code int) {
gotCode = code
done <- struct{}{}
done <- struct{}{} // we can't let this function return
}
var gotOutput bytes.Buffer

rootCmd := NewRootCmd()
rootCmd.SetErr(&gotOutput)
rootCmd.SetArgs([]string{"tenant", "update", "-n", "test", "--approvesdc", "true"})

go rootCmd.Execute()
<-done

wantCode := 1
if gotCode != wantCode {
t.Errorf("got exit code %d, want %d", gotCode, wantCode)
}
var gotErr CommandError
if err := json.NewDecoder(&gotOutput).Decode(&gotErr); err != nil {
t.Fatal(err)
}
wantErrMsg := "test error"
if gotErr.ErrorMsg != wantErrMsg {
t.Errorf("got err %q, want %q", gotErr.ErrorMsg, wantErrMsg)
}
})
}
4 changes: 3 additions & 1 deletion cmd/proxy-server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"karavi-authorization/internal/quota"
"karavi-authorization/internal/role-service"
"karavi-authorization/internal/role-service/roles"
"karavi-authorization/internal/sdc"
"karavi-authorization/internal/storage-service"
"karavi-authorization/internal/token"
"karavi-authorization/internal/token/jwx"
Expand Down Expand Up @@ -253,6 +254,7 @@ func run(log *logrus.Entry) error {
}
}()
enf := quota.NewRedisEnforcement(context.Background(), quota.WithRedis(rdb))
sdcapr := sdc.NewSdcApprover(context.Background(), sdc.WithRedis(rdb))

// Start tracing support

Expand Down Expand Up @@ -312,7 +314,7 @@ func run(log *logrus.Entry) error {
sysViper.WatchConfig()

// Create handlers for the supported storage arrays.
powerFlexHandler := proxy.NewPowerFlexHandler(log, enf, cfg.OpenPolicyAgent.Host)
powerFlexHandler := proxy.NewPowerFlexHandler(log, enf, sdcapr, cfg.OpenPolicyAgent.Host)
powerMaxHandler := proxy.NewPowerMaxHandler(log, enf, cfg.OpenPolicyAgent.Host)
powerScaleHandler := proxy.NewPowerScaleHandler(log, enf, cfg.OpenPolicyAgent.Host)

Expand Down
2 changes: 1 addition & 1 deletion cmd/proxy-server/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func TestUpdateStorageSystems(t *testing.T) {
logger := logrus.NewEntry(logrus.New())

powerScaleHandler := proxy.NewPowerScaleHandler(logger, nil, "")
powerFlexHandler := proxy.NewPowerFlexHandler(logger, nil, "")
powerFlexHandler := proxy.NewPowerFlexHandler(logger, nil, nil, "")
powerMaxHandler := proxy.NewPowerMaxHandler(logger, nil, "")

// When
Expand Down
Loading