mirror of
https://github.com/hanzoai/deploy.git
synced 2026-10-07 08:44:50 +00:00
go.mod still declared `module github.com/hanzoai/deploy` after the repo was renamed. A Go module path is not cosmetic — it is the resolvable location. So `go get github.com/hanzoai/cd` could not work, and anything importing this module had to spell a name that no longer exists at that address. The build log of v3.6.0 is where it surfaced: the compiler was still emitting github.com/hanzoai/deploy/cmd/cd/commands. 3541 import paths across 690 .go, 19 .proto, 4 .yaml, 3 .sh, 2 .mod, Procfile and Makefile. Plus the 62 ghcr.io/hanzoai/deploy image references, moved to ghcr.io/hanzoai/cd to match hanzo.yml's build target — a distinct string from the module path, replaced separately so neither could clobber the other. go mod tidy clean, CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build ./... clean. Co-authored-by: Hanzo Dev <[email protected]>
550 lines
18 KiB
Go
550 lines
18 KiB
Go
package kube
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/hanzoai/cd/gitops-engine/pkg/utils/kube/mocks"
|
|
testingutils "github.com/hanzoai/cd/gitops-engine/pkg/utils/testing"
|
|
"github.com/hanzoai/cd/gitops-engine/pkg/utils/tracing"
|
|
"github.com/go-logr/logr"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/mock"
|
|
"github.com/stretchr/testify/require"
|
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
|
"k8s.io/cli-runtime/pkg/printers"
|
|
"k8s.io/client-go/kubernetes"
|
|
kubefake "k8s.io/client-go/kubernetes/fake"
|
|
"k8s.io/client-go/rest"
|
|
"k8s.io/kubectl/pkg/cmd/apply"
|
|
"k8s.io/kubectl/pkg/cmd/create"
|
|
"k8s.io/kubectl/pkg/cmd/replace"
|
|
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
|
)
|
|
|
|
func newTestKubectlResourceOperations(t *testing.T) (*kubectlResourceOperations, *mocks.KubectlOptionsRunner) {
|
|
t.Helper()
|
|
|
|
cmdMocks := mocks.NewKubectlOptionsRunner(t)
|
|
|
|
k := &kubectlResourceOperations{
|
|
config: &rest.Config{},
|
|
log: logr.Discard(),
|
|
tracer: &tracing.NopTracer{},
|
|
fact: cmdutil.NewFactory(cmdutil.NewMatchVersionFlags(genericclioptions.NewConfigFlags(true))),
|
|
optionsRunner: cmdMocks,
|
|
getClientFunc: func() (kubernetes.Interface, error) {
|
|
return kubefake.NewSimpleClientset(), nil
|
|
},
|
|
outputMode: outputModeLog,
|
|
}
|
|
return k, cmdMocks
|
|
}
|
|
|
|
func TestAuthReconcileWithMissingNamespace(t *testing.T) {
|
|
t.Parallel()
|
|
namespace := "test-ns"
|
|
|
|
t.Run("Namespaced resources", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, _ := newTestKubectlResourceOperations(t)
|
|
|
|
role := testingutils.NewRole()
|
|
role.SetNamespace(namespace)
|
|
|
|
_, err := k.rbacReconcile(t.Context(), role, cmdutil.DryRunNone)
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), `namespaces "test-ns" not found`)
|
|
|
|
roleBinding := testingutils.NewRoleBinding()
|
|
roleBinding.SetNamespace(namespace)
|
|
|
|
_, err = k.rbacReconcile(t.Context(), roleBinding, cmdutil.DryRunNone)
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), `namespaces "test-ns" not found`)
|
|
})
|
|
|
|
t.Run("Cluster-scoped resources", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
cmdMocks.On("AuthReconcile", mock.Anything).Return(nil).Twice()
|
|
|
|
clusterRole := testingutils.NewClusterRole()
|
|
clusterRole.SetNamespace(namespace)
|
|
|
|
_, err := k.rbacReconcile(t.Context(), clusterRole, cmdutil.DryRunNone)
|
|
require.NoError(t, err)
|
|
|
|
clusterRoleBinding := testingutils.NewClusterRoleBinding()
|
|
clusterRoleBinding.SetNamespace(namespace)
|
|
|
|
_, err = k.rbacReconcile(t.Context(), clusterRoleBinding, cmdutil.DryRunNone)
|
|
require.NoError(t, err)
|
|
})
|
|
}
|
|
|
|
func TestAuthReconcileUsage(t *testing.T) {
|
|
t.Parallel()
|
|
// This test verifies that the rbacReconcile logic is correctly applied based on the operation type
|
|
// and server-side apply setting.
|
|
|
|
role := testingutils.NewRole()
|
|
|
|
t.Run("CreateResource should not call auth reconcile", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
cmdMocks.On("Create", mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
|
|
|
_, err := k.CreateResource(t.Context(), role, cmdutil.DryRunNone, false)
|
|
require.NoError(t, err)
|
|
cmdMocks.AssertNotCalled(t, "AuthReconcile")
|
|
})
|
|
|
|
t.Run("ReplaceResource should not call auth reconcile", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
cmdMocks.On("Replace", mock.Anything, mock.Anything).Return(nil)
|
|
|
|
_, err := k.ReplaceResource(t.Context(), role, cmdutil.DryRunNone, false)
|
|
require.NoError(t, err)
|
|
cmdMocks.AssertNotCalled(t, "AuthReconcile")
|
|
})
|
|
|
|
t.Run("ApplyResource should not call auth reconcile on server-side apply", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
cmdMocks.On("Apply", mock.Anything).Return(nil)
|
|
|
|
ssa := true
|
|
_, err := k.ApplyResource(t.Context(), role, cmdutil.DryRunNone, false, false, ssa, "")
|
|
require.NoError(t, err)
|
|
cmdMocks.AssertNotCalled(t, "AuthReconcile")
|
|
})
|
|
|
|
t.Run("ApplyResource should call auth reconcile on client-side apply", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
cmdMocks.On("Apply", mock.Anything).Return(nil)
|
|
cmdMocks.On("AuthReconcile", mock.Anything).Return(nil)
|
|
|
|
ssa := false
|
|
_, err := k.ApplyResource(t.Context(), role, cmdutil.DryRunNone, false, false, ssa, "")
|
|
require.NoError(t, err)
|
|
})
|
|
}
|
|
|
|
func TestOutputModeLog(t *testing.T) {
|
|
t.Parallel()
|
|
// Test normal flow operations with outputModeLog
|
|
|
|
t.Run("CreateResource with outputModeLog", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
cmdMocks.On("Create", mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
|
|
|
obj := testingutils.NewPod()
|
|
_, err := k.CreateResource(t.Context(), obj, cmdutil.DryRunNone, false)
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("ReplaceResource with outputModeLog", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
cmdMocks.On("Replace", mock.Anything, mock.Anything).Return(nil)
|
|
|
|
obj := testingutils.NewPod()
|
|
_, err := k.ReplaceResource(t.Context(), obj, cmdutil.DryRunNone, false)
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("ApplyResource with outputModeLog and client-side apply", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
cmdMocks.On("Apply", mock.Anything).Return(nil)
|
|
|
|
obj := testingutils.NewPod()
|
|
_, err := k.ApplyResource(t.Context(), obj, cmdutil.DryRunNone, false, false, false, "test-manager")
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("ApplyResource with outputModeLog and server-side apply", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
cmdMocks.On("Apply", mock.Anything).Return(nil)
|
|
|
|
obj := testingutils.NewPod()
|
|
_, err := k.ApplyResource(t.Context(), obj, cmdutil.DryRunNone, false, false, true, "test-manager")
|
|
require.NoError(t, err)
|
|
})
|
|
}
|
|
|
|
func TestOutputModeJSON(t *testing.T) {
|
|
t.Parallel()
|
|
// Test JSON output mode operations
|
|
|
|
t.Run("CreateResource with outputModeJSON should fail", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, _ := newTestKubectlResourceOperations(t)
|
|
k.outputMode = outputModeJSON
|
|
|
|
obj := testingutils.NewPod()
|
|
_, err := k.CreateResource(t.Context(), obj, cmdutil.DryRunServer, false)
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "CreateResource is not supported with JSON output mode")
|
|
})
|
|
|
|
t.Run("ReplaceResource with outputModeJSON should fail", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, _ := newTestKubectlResourceOperations(t)
|
|
k.outputMode = outputModeJSON
|
|
|
|
obj := testingutils.NewPod()
|
|
_, err := k.ReplaceResource(t.Context(), obj, cmdutil.DryRunServer, false)
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "ReplaceResource is not supported with JSON output mode")
|
|
})
|
|
|
|
t.Run("ApplyResource with outputModeJSON without Dry run", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, _ := newTestKubectlResourceOperations(t)
|
|
k.outputMode = outputModeJSON
|
|
|
|
obj := testingutils.NewPod()
|
|
_, err := k.ApplyResource(t.Context(), obj, cmdutil.DryRunNone, false, false, true, "test-manager")
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "invalid dry run strategy used with JSON output")
|
|
})
|
|
|
|
t.Run("ApplyResource with outputModeJSON requires DryRunServer", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, _ := newTestKubectlResourceOperations(t)
|
|
k.outputMode = outputModeJSON
|
|
|
|
obj := testingutils.NewPod()
|
|
_, err := k.ApplyResource(t.Context(), obj, cmdutil.DryRunClient, false, false, true, "test-manager")
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "invalid dry run strategy used with JSON output")
|
|
})
|
|
|
|
t.Run("ApplyResource with outputModeJSON requires server-side apply", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, _ := newTestKubectlResourceOperations(t)
|
|
k.outputMode = outputModeJSON
|
|
|
|
obj := testingutils.NewPod()
|
|
_, err := k.ApplyResource(t.Context(), obj, cmdutil.DryRunServer, false, false, false, "test-manager")
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "invalid Apply strategy used with JSON output")
|
|
})
|
|
|
|
t.Run("ApplyResource with outputModeJSON return object", func(t *testing.T) {
|
|
t.Parallel()
|
|
obj := testingutils.NewPod()
|
|
jsonObj, err := json.Marshal(obj)
|
|
require.NoError(t, err)
|
|
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
k.outputMode = outputModeJSON
|
|
cmdMocks.On("Apply", mock.Anything).Run(func(args mock.Arguments) {
|
|
applyOpts := args[0].(*apply.ApplyOptions)
|
|
_, err := applyOpts.Out.Write(jsonObj)
|
|
require.NoError(t, err)
|
|
}).Return(nil)
|
|
|
|
result, err := k.ApplyResource(t.Context(), obj, cmdutil.DryRunServer, false, false, true, "test-manager")
|
|
require.NoError(t, err)
|
|
assert.JSONEq(t, string(jsonObj), result)
|
|
})
|
|
|
|
t.Run("ApplyResource with outputModeJSON with object and stderr returns object", func(t *testing.T) {
|
|
t.Parallel()
|
|
obj := testingutils.NewPod()
|
|
jsonObj, err := json.Marshal(obj)
|
|
require.NoError(t, err)
|
|
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
k.outputMode = outputModeJSON
|
|
cmdMocks.On("Apply", mock.Anything).Run(func(args mock.Arguments) {
|
|
applyOpts := args[0].(*apply.ApplyOptions)
|
|
_, err := applyOpts.Out.Write(jsonObj)
|
|
require.NoError(t, err)
|
|
|
|
// add an stderr message that should not be returned in the result
|
|
_, err = applyOpts.ErrOut.Write([]byte("error message"))
|
|
require.NoError(t, err)
|
|
}).Return(nil)
|
|
|
|
result, err := k.ApplyResource(t.Context(), obj, cmdutil.DryRunServer, false, false, true, "test-manager")
|
|
require.NoError(t, err)
|
|
assert.JSONEq(t, string(jsonObj), result)
|
|
})
|
|
|
|
t.Run("ApplyResource with outputModeJSON without object with a stderr returns error", func(t *testing.T) {
|
|
t.Parallel()
|
|
obj := testingutils.NewPod()
|
|
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
k.outputMode = outputModeJSON
|
|
cmdMocks.On("Apply", mock.Anything).Run(func(args mock.Arguments) {
|
|
applyOpts := args[0].(*apply.ApplyOptions)
|
|
|
|
_, err := applyOpts.ErrOut.Write([]byte("error message"))
|
|
require.NoError(t, err)
|
|
}).Return(nil)
|
|
|
|
_, err := k.ApplyResource(t.Context(), obj, cmdutil.DryRunServer, false, false, true, "test-manager")
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "error message")
|
|
})
|
|
}
|
|
|
|
func TestApplyOptionsConfiguration(t *testing.T) {
|
|
t.Parallel()
|
|
// Test that newApplyOptions correctly configures all ApplyOptions fields
|
|
t.Run("general options are correctly set", func(t *testing.T) {
|
|
t.Parallel()
|
|
testCases := []struct {
|
|
name string
|
|
strategy cmdutil.DryRunStrategy
|
|
}{
|
|
{"DryRunNone", cmdutil.DryRunNone},
|
|
{"DryRunClient", cmdutil.DryRunClient},
|
|
{"DryRunServer", cmdutil.DryRunServer},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
|
|
var capturedOpts *apply.ApplyOptions
|
|
cmdMocks.On("Apply", mock.Anything).Run(func(args mock.Arguments) {
|
|
capturedOpts = args[0].(*apply.ApplyOptions)
|
|
}).Return(nil)
|
|
|
|
obj := testingutils.NewPod()
|
|
_, err := k.ApplyResource(t.Context(), obj, tc.strategy, false, false, false, "test-manager")
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, tc.strategy, capturedOpts.DryRunStrategy)
|
|
assert.Equal(t, "test-manager", capturedOpts.FieldManager)
|
|
assert.True(t, capturedOpts.Overwrite)
|
|
if tc.strategy == cmdutil.DryRunClient {
|
|
// workaround for https://github.com/kubernetes/kubernetes/issues/139538
|
|
// in kubectl v1.36
|
|
assert.False(t, capturedOpts.OpenAPIPatch)
|
|
} else {
|
|
assert.True(t, capturedOpts.OpenAPIPatch)
|
|
}
|
|
assert.False(t, capturedOpts.ServerSideApply)
|
|
assert.False(t, capturedOpts.ForceConflicts)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("serverSideApply=true sets ServerSideApply=true and ForceConflicts=true", func(t *testing.T) {
|
|
t.Parallel()
|
|
testCases := []struct {
|
|
name string
|
|
strategy cmdutil.DryRunStrategy
|
|
expectedError string
|
|
}{
|
|
{"DryRunNone", cmdutil.DryRunNone, ""},
|
|
{"DryRunClient", cmdutil.DryRunClient, "error validating options: --dry-run=client doesn't work with --server-side"},
|
|
{"DryRunServer", cmdutil.DryRunServer, ""},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
|
|
var capturedOpts *apply.ApplyOptions
|
|
if tc.expectedError == "" {
|
|
cmdMocks.On("Apply", mock.Anything).Run(func(args mock.Arguments) {
|
|
capturedOpts = args[0].(*apply.ApplyOptions)
|
|
}).Return(nil)
|
|
}
|
|
|
|
ssa := true
|
|
obj := testingutils.NewPod()
|
|
_, err := k.ApplyResource(t.Context(), obj, tc.strategy, false, false, ssa, "test-manager")
|
|
|
|
if tc.expectedError == "" {
|
|
require.NoError(t, err)
|
|
assert.True(t, capturedOpts.ServerSideApply)
|
|
assert.True(t, capturedOpts.ForceConflicts)
|
|
} else {
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), tc.expectedError)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("force=true sets DeleteOptions.ForceDeletion", func(t *testing.T) {
|
|
t.Parallel()
|
|
testCases := []struct {
|
|
name string
|
|
strategy cmdutil.DryRunStrategy
|
|
}{
|
|
{"DryRunNone", cmdutil.DryRunNone},
|
|
{"DryRunClient", cmdutil.DryRunClient},
|
|
{"DryRunServer", cmdutil.DryRunServer},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
|
|
var capturedOpts *apply.ApplyOptions
|
|
cmdMocks.On("Apply", mock.Anything).Run(func(args mock.Arguments) {
|
|
capturedOpts = args[0].(*apply.ApplyOptions)
|
|
}).Return(nil)
|
|
|
|
obj := testingutils.NewPod()
|
|
_, err := k.ApplyResource(t.Context(), obj, cmdutil.DryRunNone, true, false, false, "")
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, capturedOpts.DeleteOptions.ForceDeletion)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("outputModeJSON returns JSONPrinter", func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
k.outputMode = outputModeJSON
|
|
|
|
var capturedOpts *apply.ApplyOptions
|
|
cmdMocks.On("Apply", mock.Anything).Run(func(args mock.Arguments) {
|
|
capturedOpts = args[0].(*apply.ApplyOptions)
|
|
}).Return(nil)
|
|
|
|
obj := testingutils.NewPod()
|
|
_, err := k.ApplyResource(t.Context(), obj, cmdutil.DryRunServer, false, false, true, "test-manager")
|
|
require.NoError(t, err)
|
|
|
|
// Call ToPrinter and verify it returns a JSON printer
|
|
printer, err := capturedOpts.ToPrinter("configured")
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, printer)
|
|
|
|
// Verify it's a JSONPrinter by checking the type
|
|
_, isJSONPrinter := printer.(*printers.JSONPrinter)
|
|
assert.True(t, isJSONPrinter, "Expected printer to be of type *printers.JSONPrinter")
|
|
|
|
// Verify ShowManagedFields is set to true for JSON output
|
|
assert.True(t, capturedOpts.PrintFlags.JSONYamlPrintFlags.ShowManagedFields)
|
|
})
|
|
}
|
|
|
|
func TestCreateOptionsConfiguration(t *testing.T) {
|
|
t.Parallel()
|
|
// Test that newCreateOptions correctly configures all CreateOptions fields
|
|
|
|
t.Run("general options are correctly set", func(t *testing.T) {
|
|
t.Parallel()
|
|
testCases := []struct {
|
|
name string
|
|
strategy cmdutil.DryRunStrategy
|
|
}{
|
|
{"DryRunNone", cmdutil.DryRunNone},
|
|
{"DryRunClient", cmdutil.DryRunClient},
|
|
{"DryRunServer", cmdutil.DryRunServer},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
|
|
var capturedOpts *create.CreateOptions
|
|
cmdMocks.On("Create", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
|
capturedOpts = args[0].(*create.CreateOptions)
|
|
}).Return(nil)
|
|
|
|
obj := testingutils.NewPod()
|
|
_, err := k.CreateResource(t.Context(), obj, tc.strategy, false)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, tc.strategy, capturedOpts.DryRunStrategy)
|
|
assert.NotEmpty(t, capturedOpts.FilenameOptions.Filenames)
|
|
assert.NotNil(t, capturedOpts.PrintObj)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReplaceOptionsConfiguration(t *testing.T) {
|
|
t.Parallel()
|
|
// Test that newReplaceOptions correctly configures all ReplaceOptions fields
|
|
|
|
t.Run("general options are correctly set", func(t *testing.T) {
|
|
t.Parallel()
|
|
testCases := []struct {
|
|
name string
|
|
strategy cmdutil.DryRunStrategy
|
|
}{
|
|
{"DryRunNone", cmdutil.DryRunNone},
|
|
{"DryRunClient", cmdutil.DryRunClient},
|
|
{"DryRunServer", cmdutil.DryRunServer},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
|
|
var capturedOpts *replace.ReplaceOptions
|
|
cmdMocks.On("Replace", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
|
capturedOpts = args[0].(*replace.ReplaceOptions)
|
|
}).Return(nil)
|
|
|
|
obj := testingutils.NewPod()
|
|
obj.SetNamespace("test-namespace")
|
|
_, err := k.ReplaceResource(t.Context(), obj, tc.strategy, false)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, tc.strategy, capturedOpts.DryRunStrategy)
|
|
assert.False(t, capturedOpts.DeleteOptions.ForceDeletion)
|
|
assert.NotEmpty(t, capturedOpts.DeleteOptions.Filenames)
|
|
assert.Equal(t, "test-namespace", capturedOpts.Namespace)
|
|
assert.NotNil(t, capturedOpts.PrintObj)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("force=true sets DeleteOptions.ForceDeletion correctly", func(t *testing.T) {
|
|
t.Parallel()
|
|
testCases := []struct {
|
|
name string
|
|
strategy cmdutil.DryRunStrategy
|
|
expected bool
|
|
}{
|
|
{"DryRunNone", cmdutil.DryRunNone, true},
|
|
{"DryRunClient", cmdutil.DryRunClient, false},
|
|
{"DryRunServer", cmdutil.DryRunServer, false},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
k, cmdMocks := newTestKubectlResourceOperations(t)
|
|
|
|
var capturedOpts *replace.ReplaceOptions
|
|
cmdMocks.On("Replace", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
|
capturedOpts = args[0].(*replace.ReplaceOptions)
|
|
}).Return(nil)
|
|
|
|
obj := testingutils.NewPod()
|
|
_, err := k.ReplaceResource(t.Context(), obj, tc.strategy, true)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, tc.expected, capturedOpts.DeleteOptions.ForceDeletion)
|
|
})
|
|
}
|
|
})
|
|
}
|