mirror of
https://github.com/kastenhq/kubestr.git
synced 2024-12-14 11:57:56 +00:00
Adding --show-tree flag to both "./kubestr browse pvc" & "./kubestr browse snapshot" commands (#278)
* Adding the kubestr browse pvc command. Handling kubestr browse support for backward compatibility. * Adding browse snapshot command. Updating browse command to browse pvc command. * chore(deps): bump github/codeql-action in the github-actions group (#272) Bumps the github-actions group with 1 update: [github/codeql-action](https://github.com/github/codeql-action). Updates `github/codeql-action` from 3.25.12 to 3.25.13 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](4fa2a79536...2d790406f5
) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump docker/build-push-action in the docker group (#273) Bumps the docker group with 1 update: [docker/build-push-action](https://github.com/docker/build-push-action). Updates `docker/build-push-action` from 6.3.0 to 6.4.1 - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](1a162644f9...1ca370b3a9
) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docker ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Adding --show-tree flag for browse snapshot & browse pvc commands * Removing unused snapshot function parameter in cleanup * Adding KubeExecutor Exec helper function to execute tree command * Adding --show-tree logic in pvc_inspector.go * Adding --show-tree logic in snapshot_inspector.go * Printing out the tree structure for --show-tree * Updating mock tests for new code changes * Updating mount path in container args for creating a browse pod * Updating the CSITestSuite.TestCreateInspectorApplication for changes in the mount path * Adding Deprecated msg to the 'browse' command * Adding mock tests for SnapshotBrowserStepper * Adding fake tests for snapshot_inspector.go * Renamed testcase CSITestSuite.TestCreateInspectorApplication to TestCreateInspectorApplicationForPVC * Adding snapshot_inspector_steps_test.go * Updating mock tests for new code changes * Updating the mount paths in CSITestSuite.TestCreateInspectorApplicationForSnapshot * Updating Deprecated msg for 'browse' command * Making namespace, runAsUser & localport flags persistent * Removing namespace, runAsUser & localport flags for browse snapshot because we made those persistent * Adding --show-tree flag for browse snapshot & browse pvc commands * Updating namespace flag usage for better understanding * Removing storage class flag * Adding --show-tree logic in snapshot_inspector.go * Updating mock objects for SnapshotBrowserStepper * Adding --show-tree flag for browse snapshot & browse pvc commands * Removing storage class flag * Adding --show-tree flag for browse snapshot & browse pvc commands * Adding --show-tree logic in snapshot_inspector.go * Passing showTree var as function argument * Making --show-tree a persistent flag * Removing ShowTree dummy condition * Removing duplicate browseSnapshotCmd * Adding --show-tree flag for browse snapshot & browse pvc commands * Making --show-tree a persistent flag * Adding --show-tree flag for browse snapshot & browse pvc commands * Making --show-tree a persistent flag --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
parent
2cf1758a0c
commit
8037d9456d
10 changed files with 205 additions and 17 deletions
|
@ -95,6 +95,8 @@ var (
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showTree bool
|
||||||
|
|
||||||
browsePvcCmd = &cobra.Command{
|
browsePvcCmd = &cobra.Command{
|
||||||
Use: "pvc [PVC name]",
|
Use: "pvc [PVC name]",
|
||||||
Short: "Browse the contents of a CSI PVC via file browser",
|
Short: "Browse the contents of a CSI PVC via file browser",
|
||||||
|
@ -106,6 +108,7 @@ var (
|
||||||
csiCheckVolumeSnapshotClass,
|
csiCheckVolumeSnapshotClass,
|
||||||
csiCheckRunAsUser,
|
csiCheckRunAsUser,
|
||||||
browseLocalPort,
|
browseLocalPort,
|
||||||
|
showTree,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -120,6 +123,7 @@ var (
|
||||||
namespace,
|
namespace,
|
||||||
csiCheckRunAsUser,
|
csiCheckRunAsUser,
|
||||||
browseLocalPort,
|
browseLocalPort,
|
||||||
|
showTree,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -195,6 +199,7 @@ func init() {
|
||||||
browseCmd.PersistentFlags().StringVarP(&namespace, "namespace", "n", fio.DefaultNS, "The namespace of the resource to browse.")
|
browseCmd.PersistentFlags().StringVarP(&namespace, "namespace", "n", fio.DefaultNS, "The namespace of the resource to browse.")
|
||||||
browseCmd.PersistentFlags().Int64VarP(&csiCheckRunAsUser, "runAsUser", "u", 0, "Runs the inspector pod as a user (int)")
|
browseCmd.PersistentFlags().Int64VarP(&csiCheckRunAsUser, "runAsUser", "u", 0, "Runs the inspector pod as a user (int)")
|
||||||
browseCmd.PersistentFlags().IntVarP(&browseLocalPort, "localport", "l", 8080, "The local port to expose the inspector")
|
browseCmd.PersistentFlags().IntVarP(&browseLocalPort, "localport", "l", 8080, "The local port to expose the inspector")
|
||||||
|
browseCmd.PersistentFlags().BoolVarP(&showTree, "show-tree", "t", false, "Prints the contents of given PVC or VolumeSnapshot")
|
||||||
|
|
||||||
browseCmd.AddCommand(browsePvcCmd)
|
browseCmd.AddCommand(browsePvcCmd)
|
||||||
browsePvcCmd.Flags().StringVarP(&csiCheckVolumeSnapshotClass, "volumesnapshotclass", "v", "", "The name of a VolumeSnapshotClass. (Required)")
|
browsePvcCmd.Flags().StringVarP(&csiCheckVolumeSnapshotClass, "volumesnapshotclass", "v", "", "The name of a VolumeSnapshotClass. (Required)")
|
||||||
|
@ -361,6 +366,7 @@ func CsiPvcBrowse(ctx context.Context,
|
||||||
volumeSnapshotClass string,
|
volumeSnapshotClass string,
|
||||||
runAsUser int64,
|
runAsUser int64,
|
||||||
localPort int,
|
localPort int,
|
||||||
|
showTree bool,
|
||||||
) error {
|
) error {
|
||||||
kubecli, err := kubestr.LoadKubeCli()
|
kubecli, err := kubestr.LoadKubeCli()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -382,6 +388,7 @@ func CsiPvcBrowse(ctx context.Context,
|
||||||
VolumeSnapshotClass: volumeSnapshotClass,
|
VolumeSnapshotClass: volumeSnapshotClass,
|
||||||
RunAsUser: runAsUser,
|
RunAsUser: runAsUser,
|
||||||
LocalPort: localPort,
|
LocalPort: localPort,
|
||||||
|
ShowTree: showTree,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to run PVC browser (%s)\n", err.Error())
|
fmt.Printf("Failed to run PVC browser (%s)\n", err.Error())
|
||||||
|
@ -394,6 +401,7 @@ func CsiSnapshotBrowse(ctx context.Context,
|
||||||
namespace string,
|
namespace string,
|
||||||
runAsUser int64,
|
runAsUser int64,
|
||||||
localPort int,
|
localPort int,
|
||||||
|
showTree bool,
|
||||||
) error {
|
) error {
|
||||||
kubecli, err := kubestr.LoadKubeCli()
|
kubecli, err := kubestr.LoadKubeCli()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -414,6 +422,7 @@ func CsiSnapshotBrowse(ctx context.Context,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
RunAsUser: runAsUser,
|
RunAsUser: runAsUser,
|
||||||
LocalPort: localPort,
|
LocalPort: localPort,
|
||||||
|
ShowTree: showTree,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to run Snapshot browser (%s)\n", err.Error())
|
fmt.Printf("Failed to run Snapshot browser (%s)\n", err.Error())
|
||||||
|
|
|
@ -568,3 +568,20 @@ func (p *portforward) PortForwardAPod(req *types.PortForwardAPodRequest) error {
|
||||||
func (p *portforward) FetchRestConfig() (*rest.Config, error) {
|
func (p *portforward) FetchRestConfig() (*rest.Config, error) {
|
||||||
return kube.LoadConfig()
|
return kube.LoadConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:generate go run github.com/golang/mock/mockgen -destination=mocks/mock_kube_executor.go -package=mocks . KubeExecutor
|
||||||
|
type KubeExecutor interface {
|
||||||
|
Exec(ctx context.Context, namespace string, podName string, ContainerName string, command []string) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type kubeExec struct {
|
||||||
|
kubeCli kubernetes.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *kubeExec) Exec(ctx context.Context, namespace string, podName string, ContainerName string, command []string) (string, error) {
|
||||||
|
if k.kubeCli == nil {
|
||||||
|
return "", fmt.Errorf("kubeCli not initialized")
|
||||||
|
}
|
||||||
|
stdout, _, err := kankube.Exec(ctx, k.kubeCli, namespace, podName, ContainerName, command, nil)
|
||||||
|
return stdout, err
|
||||||
|
}
|
||||||
|
|
50
pkg/csi/mocks/mock_kube_executor.go
Normal file
50
pkg/csi/mocks/mock_kube_executor.go
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: github.com/kastenhq/kubestr/pkg/csi (interfaces: KubeExecutor)
|
||||||
|
|
||||||
|
// Package mocks is a generated GoMock package.
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockKubeExecutor is a mock of KubeExecutor interface.
|
||||||
|
type MockKubeExecutor struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockKubeExecutorMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockKubeExecutorMockRecorder is the mock recorder for MockKubeExecutor.
|
||||||
|
type MockKubeExecutorMockRecorder struct {
|
||||||
|
mock *MockKubeExecutor
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockKubeExecutor creates a new mock instance.
|
||||||
|
func NewMockKubeExecutor(ctrl *gomock.Controller) *MockKubeExecutor {
|
||||||
|
mock := &MockKubeExecutor{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockKubeExecutorMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockKubeExecutor) EXPECT() *MockKubeExecutorMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exec mocks base method.
|
||||||
|
func (m *MockKubeExecutor) Exec(arg0 context.Context, arg1, arg2, arg3 string, arg4 []string) (string, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Exec", arg0, arg1, arg2, arg3, arg4)
|
||||||
|
ret0, _ := ret[0].(string)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exec indicates an expected call of Exec.
|
||||||
|
func (mr *MockKubeExecutorMockRecorder) Exec(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Exec", reflect.TypeOf((*MockKubeExecutor)(nil).Exec), arg0, arg1, arg2, arg3, arg4)
|
||||||
|
}
|
|
@ -66,6 +66,21 @@ func (mr *MockPVCBrowserStepperMockRecorder) CreateInspectorApplication(arg0, ar
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateInspectorApplication", reflect.TypeOf((*MockPVCBrowserStepper)(nil).CreateInspectorApplication), arg0, arg1, arg2, arg3)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateInspectorApplication", reflect.TypeOf((*MockPVCBrowserStepper)(nil).CreateInspectorApplication), arg0, arg1, arg2, arg3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecuteTreeCommand mocks base method.
|
||||||
|
func (m *MockPVCBrowserStepper) ExecuteTreeCommand(arg0 context.Context, arg1 *types.PVCBrowseArgs, arg2 *v10.Pod) (string, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ExecuteTreeCommand", arg0, arg1, arg2)
|
||||||
|
ret0, _ := ret[0].(string)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExecuteTreeCommand indicates an expected call of ExecuteTreeCommand.
|
||||||
|
func (mr *MockPVCBrowserStepperMockRecorder) ExecuteTreeCommand(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteTreeCommand", reflect.TypeOf((*MockPVCBrowserStepper)(nil).ExecuteTreeCommand), arg0, arg1, arg2)
|
||||||
|
}
|
||||||
|
|
||||||
// PortForwardAPod mocks base method.
|
// PortForwardAPod mocks base method.
|
||||||
func (m *MockPVCBrowserStepper) PortForwardAPod(arg0 context.Context, arg1 *v10.Pod, arg2 int) error {
|
func (m *MockPVCBrowserStepper) PortForwardAPod(arg0 context.Context, arg1 *v10.Pod, arg2 int) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
|
|
@ -66,6 +66,21 @@ func (mr *MockSnapshotBrowserStepperMockRecorder) CreateInspectorApplication(arg
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateInspectorApplication", reflect.TypeOf((*MockSnapshotBrowserStepper)(nil).CreateInspectorApplication), arg0, arg1, arg2, arg3)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateInspectorApplication", reflect.TypeOf((*MockSnapshotBrowserStepper)(nil).CreateInspectorApplication), arg0, arg1, arg2, arg3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecuteTreeCommand mocks base method.
|
||||||
|
func (m *MockSnapshotBrowserStepper) ExecuteTreeCommand(arg0 context.Context, arg1 *types.SnapshotBrowseArgs, arg2 *v10.Pod) (string, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ExecuteTreeCommand", arg0, arg1, arg2)
|
||||||
|
ret0, _ := ret[0].(string)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExecuteTreeCommand indicates an expected call of ExecuteTreeCommand.
|
||||||
|
func (mr *MockSnapshotBrowserStepperMockRecorder) ExecuteTreeCommand(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteTreeCommand", reflect.TypeOf((*MockSnapshotBrowserStepper)(nil).ExecuteTreeCommand), arg0, arg1, arg2)
|
||||||
|
}
|
||||||
|
|
||||||
// PortForwardAPod mocks base method.
|
// PortForwardAPod mocks base method.
|
||||||
func (m *MockSnapshotBrowserStepper) PortForwardAPod(arg0 context.Context, arg1 *v10.Pod, arg2 int) error {
|
func (m *MockSnapshotBrowserStepper) PortForwardAPod(arg0 context.Context, arg1 *v10.Pod, arg2 int) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
|
|
@ -49,11 +49,18 @@ func (r *PVCBrowseRunner) RunPVCBrowse(ctx context.Context, args *types.PVCBrows
|
||||||
dynCli: r.DynCli,
|
dynCli: r.DynCli,
|
||||||
},
|
},
|
||||||
portForwardOps: &portforward{},
|
portForwardOps: &portforward{},
|
||||||
|
kubeExecutor: &kubeExec{
|
||||||
|
kubeCli: r.KubeCli,
|
||||||
|
},
|
||||||
cleanerOps: &cleanse{
|
cleanerOps: &cleanse{
|
||||||
kubeCli: r.KubeCli,
|
kubeCli: r.KubeCli,
|
||||||
dynCli: r.DynCli,
|
dynCli: r.DynCli,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if args.ShowTree {
|
||||||
|
fmt.Println("Show Tree works for PVC!")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return r.RunPVCBrowseHelper(ctx, args)
|
return r.RunPVCBrowseHelper(ctx, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,19 +77,29 @@ func (r *PVCBrowseRunner) RunPVCBrowseHelper(ctx context.Context, args *types.PV
|
||||||
return errors.Wrap(err, "Failed to validate arguments.")
|
return errors.Wrap(err, "Failed to validate arguments.")
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Taking a snapshot")
|
fmt.Println("Taking a snapshot.")
|
||||||
snapName := snapshotPrefix + time.Now().Format("20060102150405")
|
snapName := snapshotPrefix + time.Now().Format("20060102150405")
|
||||||
r.snapshot, err = r.browserSteps.SnapshotPVC(ctx, args, snapName)
|
r.snapshot, err = r.browserSteps.SnapshotPVC(ctx, args, snapName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "Failed to snapshot PVC.")
|
return errors.Wrap(err, "Failed to snapshot PVC.")
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Creating the file browser application.")
|
fmt.Println("Creating the browser pod.")
|
||||||
r.pod, r.pvc, err = r.browserSteps.CreateInspectorApplication(ctx, args, r.snapshot, sc)
|
r.pod, r.pvc, err = r.browserSteps.CreateInspectorApplication(ctx, args, r.snapshot, sc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "Failed to create inspector application.")
|
return errors.Wrap(err, "Failed to create inspector application.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if args.ShowTree {
|
||||||
|
fmt.Println("Printing the tree structure from root directory.")
|
||||||
|
stdout, err := r.browserSteps.ExecuteTreeCommand(ctx, args, r.pod)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "Failed to execute tree command in pod.")
|
||||||
|
}
|
||||||
|
fmt.Printf("\n%s\n\n", stdout)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println("Forwarding the port.")
|
fmt.Println("Forwarding the port.")
|
||||||
err = r.browserSteps.PortForwardAPod(ctx, r.pod, args.LocalPort)
|
err = r.browserSteps.PortForwardAPod(ctx, r.pod, args.LocalPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -97,6 +114,7 @@ type PVCBrowserStepper interface {
|
||||||
ValidateArgs(ctx context.Context, args *types.PVCBrowseArgs) (*sv1.StorageClass, error)
|
ValidateArgs(ctx context.Context, args *types.PVCBrowseArgs) (*sv1.StorageClass, error)
|
||||||
SnapshotPVC(ctx context.Context, args *types.PVCBrowseArgs, snapshotName string) (*snapv1.VolumeSnapshot, error)
|
SnapshotPVC(ctx context.Context, args *types.PVCBrowseArgs, snapshotName string) (*snapv1.VolumeSnapshot, error)
|
||||||
CreateInspectorApplication(ctx context.Context, args *types.PVCBrowseArgs, snapshot *snapv1.VolumeSnapshot, storageClass *sv1.StorageClass) (*v1.Pod, *v1.PersistentVolumeClaim, error)
|
CreateInspectorApplication(ctx context.Context, args *types.PVCBrowseArgs, snapshot *snapv1.VolumeSnapshot, storageClass *sv1.StorageClass) (*v1.Pod, *v1.PersistentVolumeClaim, error)
|
||||||
|
ExecuteTreeCommand(ctx context.Context, args *types.PVCBrowseArgs, pod *v1.Pod) (string, error)
|
||||||
PortForwardAPod(ctx context.Context, pod *v1.Pod, localPort int) error
|
PortForwardAPod(ctx context.Context, pod *v1.Pod, localPort int) error
|
||||||
Cleanup(ctx context.Context, pvc *v1.PersistentVolumeClaim, pod *v1.Pod, snapshot *snapv1.VolumeSnapshot)
|
Cleanup(ctx context.Context, pvc *v1.PersistentVolumeClaim, pod *v1.Pod, snapshot *snapv1.VolumeSnapshot)
|
||||||
}
|
}
|
||||||
|
@ -108,6 +126,7 @@ type pvcBrowserSteps struct {
|
||||||
snapshotCreateOps SnapshotCreator
|
snapshotCreateOps SnapshotCreator
|
||||||
portForwardOps PortForwarder
|
portForwardOps PortForwarder
|
||||||
cleanerOps Cleaner
|
cleanerOps Cleaner
|
||||||
|
kubeExecutor KubeExecutor
|
||||||
SnapshotGroupVersion *metav1.GroupVersionForDiscovery
|
SnapshotGroupVersion *metav1.GroupVersionForDiscovery
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,12 +213,24 @@ func (p *pvcBrowserSteps) CreateInspectorApplication(ctx context.Context, args *
|
||||||
Namespace: args.Namespace,
|
Namespace: args.Namespace,
|
||||||
RunAsUser: args.RunAsUser,
|
RunAsUser: args.RunAsUser,
|
||||||
ContainerImage: "filebrowser/filebrowser:v2",
|
ContainerImage: "filebrowser/filebrowser:v2",
|
||||||
ContainerArgs: []string{"--noauth", "-r", "/data"},
|
ContainerArgs: []string{"--noauth", "-r", "/pvc-data"},
|
||||||
MountPath: "/data",
|
MountPath: "/pvc-data",
|
||||||
|
}
|
||||||
|
if args.ShowTree {
|
||||||
|
podArgs = &types.CreatePodArgs{
|
||||||
|
GenerateName: clonedPodGenerateName,
|
||||||
|
PVCName: pvc.Name,
|
||||||
|
Namespace: args.Namespace,
|
||||||
|
RunAsUser: args.RunAsUser,
|
||||||
|
ContainerImage: "alpine:3.19",
|
||||||
|
Command: []string{"/bin/sh"},
|
||||||
|
ContainerArgs: []string{"-c", "while true; do sleep 3600; done"},
|
||||||
|
MountPath: "/pvc-data",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pod, err := p.createAppOps.CreatePod(ctx, podArgs)
|
pod, err := p.createAppOps.CreatePod(ctx, podArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, pvc, errors.Wrap(err, "Failed to create restored Pod")
|
return nil, pvc, errors.Wrap(err, "Failed to create browse Pod")
|
||||||
}
|
}
|
||||||
if err = p.createAppOps.WaitForPodReady(ctx, args.Namespace, pod.Name); err != nil {
|
if err = p.createAppOps.WaitForPodReady(ctx, args.Namespace, pod.Name); err != nil {
|
||||||
return pod, pvc, errors.Wrap(err, "Pod failed to become ready")
|
return pod, pvc, errors.Wrap(err, "Pod failed to become ready")
|
||||||
|
@ -207,6 +238,15 @@ func (p *pvcBrowserSteps) CreateInspectorApplication(ctx context.Context, args *
|
||||||
return pod, pvc, nil
|
return pod, pvc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *pvcBrowserSteps) ExecuteTreeCommand(ctx context.Context, args *types.PVCBrowseArgs, pod *v1.Pod) (string, error) {
|
||||||
|
command := []string{"tree", "/pvc-data"}
|
||||||
|
stdout, err := p.kubeExecutor.Exec(ctx, args.Namespace, pod.Name, pod.Spec.Containers[0].Name, command)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrapf(err, "Error running command:(%v)", command)
|
||||||
|
}
|
||||||
|
return stdout, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *pvcBrowserSteps) PortForwardAPod(ctx context.Context, pod *v1.Pod, localPort int) error {
|
func (p *pvcBrowserSteps) PortForwardAPod(ctx context.Context, pod *v1.Pod, localPort int) error {
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
|
@ -541,8 +541,8 @@ func (s *CSITestSuite) TestCreateInspectorApplicationForPVC(c *C) {
|
||||||
GenerateName: clonedPodGenerateName,
|
GenerateName: clonedPodGenerateName,
|
||||||
PVCName: "pvc1",
|
PVCName: "pvc1",
|
||||||
Namespace: "ns",
|
Namespace: "ns",
|
||||||
ContainerArgs: []string{"--noauth", "-r", "/data"},
|
ContainerArgs: []string{"--noauth", "-r", "/pvc-data"},
|
||||||
MountPath: "/data",
|
MountPath: "/pvc-data",
|
||||||
RunAsUser: 100,
|
RunAsUser: 100,
|
||||||
ContainerImage: "filebrowser/filebrowser:v2",
|
ContainerImage: "filebrowser/filebrowser:v2",
|
||||||
}).Return(&v1.Pod{
|
}).Return(&v1.Pod{
|
||||||
|
@ -596,8 +596,8 @@ func (s *CSITestSuite) TestCreateInspectorApplicationForPVC(c *C) {
|
||||||
GenerateName: clonedPodGenerateName,
|
GenerateName: clonedPodGenerateName,
|
||||||
PVCName: "pvc1",
|
PVCName: "pvc1",
|
||||||
Namespace: "ns",
|
Namespace: "ns",
|
||||||
ContainerArgs: []string{"--noauth", "-r", "/data"},
|
ContainerArgs: []string{"--noauth", "-r", "/pvc-data"},
|
||||||
MountPath: "/data",
|
MountPath: "/pvc-data",
|
||||||
RunAsUser: 100,
|
RunAsUser: 100,
|
||||||
ContainerImage: "filebrowser/filebrowser:v2",
|
ContainerImage: "filebrowser/filebrowser:v2",
|
||||||
}).Return(&v1.Pod{
|
}).Return(&v1.Pod{
|
||||||
|
|
|
@ -44,11 +44,18 @@ func (r *SnapshotBrowseRunner) RunSnapshotBrowse(ctx context.Context, args *type
|
||||||
dynCli: r.DynCli,
|
dynCli: r.DynCli,
|
||||||
},
|
},
|
||||||
portForwardOps: &portforward{},
|
portForwardOps: &portforward{},
|
||||||
|
kubeExecutor: &kubeExec{
|
||||||
|
kubeCli: r.KubeCli,
|
||||||
|
},
|
||||||
cleanerOps: &cleanse{
|
cleanerOps: &cleanse{
|
||||||
kubeCli: r.KubeCli,
|
kubeCli: r.KubeCli,
|
||||||
dynCli: r.DynCli,
|
dynCli: r.DynCli,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if args.ShowTree {
|
||||||
|
fmt.Println("Show Tree works for VS!")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return r.RunSnapshotBrowseHelper(ctx, args)
|
return r.RunSnapshotBrowseHelper(ctx, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,12 +76,22 @@ func (r *SnapshotBrowseRunner) RunSnapshotBrowseHelper(ctx context.Context, args
|
||||||
}
|
}
|
||||||
r.snapshot = vs
|
r.snapshot = vs
|
||||||
|
|
||||||
fmt.Println("Creating the file browser application.")
|
fmt.Println("Creating the browser pod.")
|
||||||
r.pod, r.pvc, err = r.browserSteps.CreateInspectorApplication(ctx, args, r.snapshot, sc)
|
r.pod, r.pvc, err = r.browserSteps.CreateInspectorApplication(ctx, args, r.snapshot, sc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "Failed to create inspector application.")
|
return errors.Wrap(err, "Failed to create inspector application.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if args.ShowTree {
|
||||||
|
fmt.Println("Printing the tree structure from root directory.")
|
||||||
|
stdout, err := r.browserSteps.ExecuteTreeCommand(ctx, args, r.pod)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "Failed to execute tree command in pod.")
|
||||||
|
}
|
||||||
|
fmt.Printf("\n%s\n\n", stdout)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println("Forwarding the port.")
|
fmt.Println("Forwarding the port.")
|
||||||
err = r.browserSteps.PortForwardAPod(ctx, r.pod, args.LocalPort)
|
err = r.browserSteps.PortForwardAPod(ctx, r.pod, args.LocalPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -88,6 +105,7 @@ func (r *SnapshotBrowseRunner) RunSnapshotBrowseHelper(ctx context.Context, args
|
||||||
type SnapshotBrowserStepper interface {
|
type SnapshotBrowserStepper interface {
|
||||||
ValidateArgs(ctx context.Context, args *types.SnapshotBrowseArgs) (*snapv1.VolumeSnapshot, *sv1.StorageClass, error)
|
ValidateArgs(ctx context.Context, args *types.SnapshotBrowseArgs) (*snapv1.VolumeSnapshot, *sv1.StorageClass, error)
|
||||||
CreateInspectorApplication(ctx context.Context, args *types.SnapshotBrowseArgs, snapshot *snapv1.VolumeSnapshot, storageClass *sv1.StorageClass) (*v1.Pod, *v1.PersistentVolumeClaim, error)
|
CreateInspectorApplication(ctx context.Context, args *types.SnapshotBrowseArgs, snapshot *snapv1.VolumeSnapshot, storageClass *sv1.StorageClass) (*v1.Pod, *v1.PersistentVolumeClaim, error)
|
||||||
|
ExecuteTreeCommand(ctx context.Context, args *types.SnapshotBrowseArgs, pod *v1.Pod) (string, error)
|
||||||
PortForwardAPod(ctx context.Context, pod *v1.Pod, localPort int) error
|
PortForwardAPod(ctx context.Context, pod *v1.Pod, localPort int) error
|
||||||
Cleanup(ctx context.Context, pvc *v1.PersistentVolumeClaim, pod *v1.Pod)
|
Cleanup(ctx context.Context, pvc *v1.PersistentVolumeClaim, pod *v1.Pod)
|
||||||
}
|
}
|
||||||
|
@ -99,6 +117,7 @@ type snapshotBrowserSteps struct {
|
||||||
createAppOps ApplicationCreator
|
createAppOps ApplicationCreator
|
||||||
portForwardOps PortForwarder
|
portForwardOps PortForwarder
|
||||||
cleanerOps Cleaner
|
cleanerOps Cleaner
|
||||||
|
kubeExecutor KubeExecutor
|
||||||
SnapshotGroupVersion *metav1.GroupVersionForDiscovery
|
SnapshotGroupVersion *metav1.GroupVersionForDiscovery
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,12 +181,24 @@ func (s *snapshotBrowserSteps) CreateInspectorApplication(ctx context.Context, a
|
||||||
Namespace: args.Namespace,
|
Namespace: args.Namespace,
|
||||||
RunAsUser: args.RunAsUser,
|
RunAsUser: args.RunAsUser,
|
||||||
ContainerImage: "filebrowser/filebrowser:v2",
|
ContainerImage: "filebrowser/filebrowser:v2",
|
||||||
ContainerArgs: []string{"--noauth", "-r", "/data"},
|
ContainerArgs: []string{"--noauth", "-r", "/snapshot-data"},
|
||||||
MountPath: "/data",
|
MountPath: "/snapshot-data",
|
||||||
|
}
|
||||||
|
if args.ShowTree {
|
||||||
|
podArgs = &types.CreatePodArgs{
|
||||||
|
GenerateName: clonedPodGenerateName,
|
||||||
|
PVCName: pvc.Name,
|
||||||
|
Namespace: args.Namespace,
|
||||||
|
RunAsUser: args.RunAsUser,
|
||||||
|
ContainerImage: "alpine:3.19",
|
||||||
|
Command: []string{"/bin/sh"},
|
||||||
|
ContainerArgs: []string{"-c", "while true; do sleep 3600; done"},
|
||||||
|
MountPath: "/snapshot-data",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pod, err := s.createAppOps.CreatePod(ctx, podArgs)
|
pod, err := s.createAppOps.CreatePod(ctx, podArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, pvc, errors.Wrap(err, "Failed to create restored Pod")
|
return nil, pvc, errors.Wrap(err, "Failed to create browse Pod")
|
||||||
}
|
}
|
||||||
if err = s.createAppOps.WaitForPodReady(ctx, args.Namespace, pod.Name); err != nil {
|
if err = s.createAppOps.WaitForPodReady(ctx, args.Namespace, pod.Name); err != nil {
|
||||||
return pod, pvc, errors.Wrap(err, "Pod failed to become ready")
|
return pod, pvc, errors.Wrap(err, "Pod failed to become ready")
|
||||||
|
@ -175,6 +206,15 @@ func (s *snapshotBrowserSteps) CreateInspectorApplication(ctx context.Context, a
|
||||||
return pod, pvc, nil
|
return pod, pvc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *snapshotBrowserSteps) ExecuteTreeCommand(ctx context.Context, args *types.SnapshotBrowseArgs, pod *v1.Pod) (string, error) {
|
||||||
|
command := []string{"tree", "/snapshot-data"}
|
||||||
|
stdout, err := s.kubeExecutor.Exec(ctx, args.Namespace, pod.Name, pod.Spec.Containers[0].Name, command)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrapf(err, "Error running command:(%v)", command)
|
||||||
|
}
|
||||||
|
return stdout, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *snapshotBrowserSteps) PortForwardAPod(ctx context.Context, pod *v1.Pod, localPort int) error {
|
func (s *snapshotBrowserSteps) PortForwardAPod(ctx context.Context, pod *v1.Pod, localPort int) error {
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
|
@ -345,8 +345,8 @@ func (s *CSITestSuite) TestCreateInspectorApplicationForSnapshot(c *C) {
|
||||||
GenerateName: clonedPodGenerateName,
|
GenerateName: clonedPodGenerateName,
|
||||||
PVCName: "pvc",
|
PVCName: "pvc",
|
||||||
Namespace: "ns",
|
Namespace: "ns",
|
||||||
ContainerArgs: []string{"--noauth", "-r", "/data"},
|
ContainerArgs: []string{"--noauth", "-r", "/snapshot-data"},
|
||||||
MountPath: "/data",
|
MountPath: "/snapshot-data",
|
||||||
RunAsUser: 100,
|
RunAsUser: 100,
|
||||||
ContainerImage: "filebrowser/filebrowser:v2",
|
ContainerImage: "filebrowser/filebrowser:v2",
|
||||||
}).Return(&v1.Pod{
|
}).Return(&v1.Pod{
|
||||||
|
@ -400,8 +400,8 @@ func (s *CSITestSuite) TestCreateInspectorApplicationForSnapshot(c *C) {
|
||||||
GenerateName: clonedPodGenerateName,
|
GenerateName: clonedPodGenerateName,
|
||||||
PVCName: "pvc",
|
PVCName: "pvc",
|
||||||
Namespace: "ns",
|
Namespace: "ns",
|
||||||
ContainerArgs: []string{"--noauth", "-r", "/data"},
|
ContainerArgs: []string{"--noauth", "-r", "/snapshot-data"},
|
||||||
MountPath: "/data",
|
MountPath: "/snapshot-data",
|
||||||
RunAsUser: 100,
|
RunAsUser: 100,
|
||||||
ContainerImage: "filebrowser/filebrowser:v2",
|
ContainerImage: "filebrowser/filebrowser:v2",
|
||||||
}).Return(&v1.Pod{
|
}).Return(&v1.Pod{
|
||||||
|
|
|
@ -125,6 +125,7 @@ type PVCBrowseArgs struct {
|
||||||
VolumeSnapshotClass string
|
VolumeSnapshotClass string
|
||||||
RunAsUser int64
|
RunAsUser int64
|
||||||
LocalPort int
|
LocalPort int
|
||||||
|
ShowTree bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PVCBrowseArgs) Validate() error {
|
func (p *PVCBrowseArgs) Validate() error {
|
||||||
|
@ -139,6 +140,7 @@ type SnapshotBrowseArgs struct {
|
||||||
Namespace string
|
Namespace string
|
||||||
RunAsUser int64
|
RunAsUser int64
|
||||||
LocalPort int
|
LocalPort int
|
||||||
|
ShowTree bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SnapshotBrowseArgs) Validate() error {
|
func (p *SnapshotBrowseArgs) Validate() error {
|
||||||
|
|
Loading…
Reference in a new issue