mirror of
https://github.com/rancher/steve.git
synced 2025-09-01 15:37:31 +00:00
Adding Group, Version, Kind in Update proxy_store.go (#270)
* adding gvk completion to update method in proxy_store
This commit is contained in:
@@ -4,6 +4,7 @@ package partition
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -389,7 +390,7 @@ func ToAPIEvent(apiOp *types.APIRequest, schema *types.APISchema, event watch.Ev
|
|||||||
|
|
||||||
if event.Type == watch.Error {
|
if event.Type == watch.Error {
|
||||||
status, _ := event.Object.(*metav1.Status)
|
status, _ := event.Object.(*metav1.Status)
|
||||||
apiEvent.Error = fmt.Errorf(status.Message)
|
apiEvent.Error = errors.New(status.Message)
|
||||||
return apiEvent
|
return apiEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -40,8 +40,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
watchTimeoutEnv = "CATTLE_WATCH_TIMEOUT_SECONDS"
|
watchTimeoutEnv = "CATTLE_WATCH_TIMEOUT_SECONDS"
|
||||||
errNamespaceRequired = "metadata.namespace is required"
|
errNamespaceRequired = "metadata.namespace is required"
|
||||||
|
errResourceVersionRequired = "metadata.resourceVersion is required for update"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -515,9 +516,12 @@ func (s *Store) Update(apiOp *types.APIRequest, schema *types.APISchema, params
|
|||||||
|
|
||||||
resourceVersion := input.String("metadata", "resourceVersion")
|
resourceVersion := input.String("metadata", "resourceVersion")
|
||||||
if resourceVersion == "" {
|
if resourceVersion == "" {
|
||||||
return nil, nil, fmt.Errorf("metadata.resourceVersion is required for update")
|
return nil, nil, errors.New(errResourceVersionRequired)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gvk := attributes.GVK(schema)
|
||||||
|
input["apiVersion"], input["kind"] = gvk.ToAPIVersionAndKind()
|
||||||
|
|
||||||
opts := metav1.UpdateOptions{}
|
opts := metav1.UpdateOptions{}
|
||||||
if err := decodeParams(apiOp, &opts); err != nil {
|
if err := decodeParams(apiOp, &opts); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@@ -343,7 +343,7 @@ func TestCreate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "missing namespace in the params / should copy from apiOp",
|
name: "missing namespace in the params (should copy from apiOp)",
|
||||||
input: input{
|
input: input{
|
||||||
apiOp: &types.APIRequest{
|
apiOp: &types.APIRequest{
|
||||||
Schema: &types.APISchema{
|
Schema: &types.APISchema{
|
||||||
@@ -466,7 +466,7 @@ func TestCreate(t *testing.T) {
|
|||||||
for _, tt := range testCases {
|
for _, tt := range testCases {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
testClientFactory, err := client.NewFactory(&rest.Config{}, false)
|
testClientFactory, err := client.NewFactory(&rest.Config{}, false)
|
||||||
assert.Nil(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
fakeClient := fake.NewSimpleDynamicClient(runtime.NewScheme())
|
fakeClient := fake.NewSimpleDynamicClient(runtime.NewScheme())
|
||||||
|
|
||||||
@@ -488,3 +488,357 @@ func TestCreate(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUpdate(t *testing.T) {
|
||||||
|
type input struct {
|
||||||
|
apiOp *types.APIRequest
|
||||||
|
schema *types.APISchema
|
||||||
|
params types.APIObject
|
||||||
|
id string
|
||||||
|
}
|
||||||
|
|
||||||
|
type expected struct {
|
||||||
|
value *unstructured.Unstructured
|
||||||
|
warning []types.Warning
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
sampleCreateInput := input{
|
||||||
|
apiOp: &types.APIRequest{
|
||||||
|
Request: &http.Request{
|
||||||
|
URL: &url.URL{},
|
||||||
|
Method: http.MethodPost,
|
||||||
|
},
|
||||||
|
Schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Method: http.MethodPost,
|
||||||
|
},
|
||||||
|
schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
Attributes: map[string]interface{}{
|
||||||
|
"kind": "Secret",
|
||||||
|
"version": "v1",
|
||||||
|
"namespaced": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
params: types.APIObject{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"kind": "Secret",
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
updateCallbackFunc clientgotesting.ReactionFunc
|
||||||
|
createInput *input
|
||||||
|
updateInput input
|
||||||
|
expected expected
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "update - usual request",
|
||||||
|
updateCallbackFunc: func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return false, ret, nil
|
||||||
|
},
|
||||||
|
createInput: &sampleCreateInput,
|
||||||
|
updateInput: input{
|
||||||
|
apiOp: &types.APIRequest{
|
||||||
|
Request: &http.Request{
|
||||||
|
URL: &url.URL{},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
Schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
|
||||||
|
schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
Attributes: map[string]interface{}{
|
||||||
|
"version": "v2",
|
||||||
|
"kind": "Secret",
|
||||||
|
"namespaced": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
params: types.APIObject{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"kind": "Secret",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
value: &unstructured.Unstructured{Object: map[string]interface{}{
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"kind": "Secret",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
warning: []types.Warning{},
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "update - different apiVersion and kind (params and schema) - should copy from schema",
|
||||||
|
updateCallbackFunc: func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return false, ret, nil
|
||||||
|
},
|
||||||
|
createInput: &sampleCreateInput,
|
||||||
|
updateInput: input{
|
||||||
|
apiOp: &types.APIRequest{
|
||||||
|
Request: &http.Request{
|
||||||
|
URL: &url.URL{},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
Schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
|
||||||
|
schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
Attributes: map[string]interface{}{
|
||||||
|
"version": "v2",
|
||||||
|
"kind": "Secret",
|
||||||
|
"namespaced": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
params: types.APIObject{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ConfigMap",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
value: &unstructured.Unstructured{Object: map[string]interface{}{
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"kind": "Secret",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
warning: []types.Warning{},
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "update - missing apiVersion and kind in params - should copy from schema",
|
||||||
|
updateCallbackFunc: func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return false, ret, nil
|
||||||
|
},
|
||||||
|
createInput: &sampleCreateInput,
|
||||||
|
updateInput: input{
|
||||||
|
apiOp: &types.APIRequest{
|
||||||
|
Request: &http.Request{
|
||||||
|
URL: &url.URL{},
|
||||||
|
Method: http.MethodPost,
|
||||||
|
},
|
||||||
|
Schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Method: http.MethodPost,
|
||||||
|
},
|
||||||
|
|
||||||
|
schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
Attributes: map[string]interface{}{
|
||||||
|
"version": "v2",
|
||||||
|
"kind": "Secret",
|
||||||
|
"namespaced": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
params: types.APIObject{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
value: &unstructured.Unstructured{Object: map[string]interface{}{
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"kind": "Secret",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
warning: []types.Warning{},
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "update - missing resource version",
|
||||||
|
updateCallbackFunc: func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return false, ret, nil
|
||||||
|
},
|
||||||
|
updateInput: input{
|
||||||
|
apiOp: &types.APIRequest{
|
||||||
|
Request: &http.Request{
|
||||||
|
URL: &url.URL{},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
Schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
|
||||||
|
schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
Attributes: map[string]interface{}{
|
||||||
|
"version": "v1",
|
||||||
|
"kind": "Secret",
|
||||||
|
"namespaced": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
params: types.APIObject{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "Secret",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
value: nil,
|
||||||
|
warning: nil,
|
||||||
|
err: errors.New(errResourceVersionRequired),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "update - error request",
|
||||||
|
updateCallbackFunc: func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, nil, apierrors.NewUnauthorized("sample reason")
|
||||||
|
},
|
||||||
|
createInput: &sampleCreateInput,
|
||||||
|
updateInput: input{
|
||||||
|
apiOp: &types.APIRequest{
|
||||||
|
Request: &http.Request{
|
||||||
|
URL: &url.URL{},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
Schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
|
||||||
|
schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
Attributes: map[string]interface{}{
|
||||||
|
"kind": "Secret",
|
||||||
|
"namespaced": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
params: types.APIObject{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
value: nil,
|
||||||
|
warning: nil,
|
||||||
|
err: apierrors.NewUnauthorized("sample reason"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range testCases {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
testClientFactory, err := client.NewFactory(&rest.Config{}, false)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
fakeClient := fake.NewSimpleDynamicClient(runtime.NewScheme())
|
||||||
|
|
||||||
|
if tt.updateCallbackFunc != nil {
|
||||||
|
fakeClient.PrependReactor("update", "*", tt.updateCallbackFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
testStore := Store{
|
||||||
|
clientGetter: &testFactory{Factory: testClientFactory,
|
||||||
|
fakeClient: fakeClient,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creating the object first, so we can update it later (this function is not the SUT)
|
||||||
|
if tt.createInput != nil {
|
||||||
|
_, _, err = testStore.Create(tt.createInput.apiOp, tt.createInput.schema, tt.createInput.params)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
value, warning, err := testStore.Update(tt.updateInput.apiOp, tt.updateInput.schema, tt.updateInput.params, tt.updateInput.id)
|
||||||
|
|
||||||
|
assert.Equal(t, tt.expected.value, value)
|
||||||
|
assert.Equal(t, tt.expected.warning, warning)
|
||||||
|
|
||||||
|
if tt.expected.err != nil {
|
||||||
|
assert.Equal(t, tt.expected.err.Error(), err.Error())
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -50,8 +50,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
watchTimeoutEnv = "CATTLE_WATCH_TIMEOUT_SECONDS"
|
watchTimeoutEnv = "CATTLE_WATCH_TIMEOUT_SECONDS"
|
||||||
errNamespaceRequired = "metadata.namespace or apiOp.namespace are required"
|
errNamespaceRequired = "metadata.namespace or apiOp.namespace are required"
|
||||||
|
errResourceVersionRequired = "metadata.resourceVersion is required for update"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -598,9 +599,12 @@ func (s *Store) Update(apiOp *types.APIRequest, schema *types.APISchema, params
|
|||||||
|
|
||||||
resourceVersion := input.String("metadata", "resourceVersion")
|
resourceVersion := input.String("metadata", "resourceVersion")
|
||||||
if resourceVersion == "" {
|
if resourceVersion == "" {
|
||||||
return nil, nil, fmt.Errorf("metadata.resourceVersion is required for update")
|
return nil, nil, errors.New(errResourceVersionRequired)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gvk := attributes.GVK(schema)
|
||||||
|
input["apiVersion"], input["kind"] = gvk.ToAPIVersionAndKind()
|
||||||
|
|
||||||
opts := metav1.UpdateOptions{}
|
opts := metav1.UpdateOptions{}
|
||||||
if err := decodeParams(apiOp, &opts); err != nil {
|
if err := decodeParams(apiOp, &opts); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@@ -1104,3 +1104,357 @@ func TestCreate(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUpdate(t *testing.T) {
|
||||||
|
type input struct {
|
||||||
|
apiOp *types.APIRequest
|
||||||
|
schema *types.APISchema
|
||||||
|
params types.APIObject
|
||||||
|
id string
|
||||||
|
}
|
||||||
|
|
||||||
|
type expected struct {
|
||||||
|
value *unstructured.Unstructured
|
||||||
|
warning []types.Warning
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
sampleCreateInput := input{
|
||||||
|
apiOp: &types.APIRequest{
|
||||||
|
Request: &http.Request{
|
||||||
|
URL: &url.URL{},
|
||||||
|
Method: http.MethodPost,
|
||||||
|
},
|
||||||
|
Schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Method: http.MethodPost,
|
||||||
|
},
|
||||||
|
schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
Attributes: map[string]interface{}{
|
||||||
|
"kind": "Secret",
|
||||||
|
"version": "v1",
|
||||||
|
"namespaced": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
params: types.APIObject{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"kind": "Secret",
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
updateCallbackFunc clientgotesting.ReactionFunc
|
||||||
|
createInput *input
|
||||||
|
updateInput input
|
||||||
|
expected expected
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "update - usual request",
|
||||||
|
updateCallbackFunc: func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return false, ret, nil
|
||||||
|
},
|
||||||
|
createInput: &sampleCreateInput,
|
||||||
|
updateInput: input{
|
||||||
|
apiOp: &types.APIRequest{
|
||||||
|
Request: &http.Request{
|
||||||
|
URL: &url.URL{},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
Schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
|
||||||
|
schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
Attributes: map[string]interface{}{
|
||||||
|
"version": "v2",
|
||||||
|
"kind": "Secret",
|
||||||
|
"namespaced": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
params: types.APIObject{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"kind": "Secret",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
value: &unstructured.Unstructured{Object: map[string]interface{}{
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"kind": "Secret",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
warning: []types.Warning{},
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "update - different apiVersion and kind (params and schema) - should copy from schema",
|
||||||
|
updateCallbackFunc: func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return false, ret, nil
|
||||||
|
},
|
||||||
|
createInput: &sampleCreateInput,
|
||||||
|
updateInput: input{
|
||||||
|
apiOp: &types.APIRequest{
|
||||||
|
Request: &http.Request{
|
||||||
|
URL: &url.URL{},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
Schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
|
||||||
|
schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
Attributes: map[string]interface{}{
|
||||||
|
"version": "v2",
|
||||||
|
"kind": "Secret",
|
||||||
|
"namespaced": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
params: types.APIObject{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "ConfigMap",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
value: &unstructured.Unstructured{Object: map[string]interface{}{
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"kind": "Secret",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
warning: []types.Warning{},
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "update - missing apiVersion and kind in params - should copy from schema",
|
||||||
|
updateCallbackFunc: func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return false, ret, nil
|
||||||
|
},
|
||||||
|
createInput: &sampleCreateInput,
|
||||||
|
updateInput: input{
|
||||||
|
apiOp: &types.APIRequest{
|
||||||
|
Request: &http.Request{
|
||||||
|
URL: &url.URL{},
|
||||||
|
Method: http.MethodPost,
|
||||||
|
},
|
||||||
|
Schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Method: http.MethodPost,
|
||||||
|
},
|
||||||
|
|
||||||
|
schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
Attributes: map[string]interface{}{
|
||||||
|
"version": "v2",
|
||||||
|
"kind": "Secret",
|
||||||
|
"namespaced": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
params: types.APIObject{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
value: &unstructured.Unstructured{Object: map[string]interface{}{
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"kind": "Secret",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
warning: []types.Warning{},
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "update - missing resource version",
|
||||||
|
updateCallbackFunc: func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return false, ret, nil
|
||||||
|
},
|
||||||
|
updateInput: input{
|
||||||
|
apiOp: &types.APIRequest{
|
||||||
|
Request: &http.Request{
|
||||||
|
URL: &url.URL{},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
Schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
|
||||||
|
schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
Attributes: map[string]interface{}{
|
||||||
|
"version": "v1",
|
||||||
|
"kind": "Secret",
|
||||||
|
"namespaced": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
params: types.APIObject{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "Secret",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
value: nil,
|
||||||
|
warning: nil,
|
||||||
|
err: errors.New(errResourceVersionRequired),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "update - error request",
|
||||||
|
updateCallbackFunc: func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, nil, apierrors.NewUnauthorized("sample reason")
|
||||||
|
},
|
||||||
|
createInput: &sampleCreateInput,
|
||||||
|
updateInput: input{
|
||||||
|
apiOp: &types.APIRequest{
|
||||||
|
Request: &http.Request{
|
||||||
|
URL: &url.URL{},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
Schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Method: http.MethodPut,
|
||||||
|
},
|
||||||
|
|
||||||
|
schema: &types.APISchema{
|
||||||
|
Schema: &schemas.Schema{
|
||||||
|
ID: "testing",
|
||||||
|
Attributes: map[string]interface{}{
|
||||||
|
"kind": "Secret",
|
||||||
|
"namespaced": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
params: types.APIObject{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "testing-secret",
|
||||||
|
"namespace": "testing-ns",
|
||||||
|
"resourceVersion": "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
value: nil,
|
||||||
|
warning: nil,
|
||||||
|
err: apierrors.NewUnauthorized("sample reason"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range testCases {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
testClientFactory, err := client.NewFactory(&rest.Config{}, false)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
fakeClient := fake.NewSimpleDynamicClient(runtime.NewScheme())
|
||||||
|
|
||||||
|
if tt.updateCallbackFunc != nil {
|
||||||
|
fakeClient.PrependReactor("update", "*", tt.updateCallbackFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
testStore := Store{
|
||||||
|
clientGetter: &testFactory{Factory: testClientFactory,
|
||||||
|
fakeClient: fakeClient,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creating the object first, so we can update it later (this function is not the SUT)
|
||||||
|
if tt.createInput != nil {
|
||||||
|
_, _, err = testStore.Create(tt.createInput.apiOp, tt.createInput.schema, tt.createInput.params)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
value, warning, err := testStore.Update(tt.updateInput.apiOp, tt.updateInput.schema, tt.updateInput.params, tt.updateInput.id)
|
||||||
|
|
||||||
|
assert.Equal(t, tt.expected.value, value)
|
||||||
|
assert.Equal(t, tt.expected.warning, warning)
|
||||||
|
|
||||||
|
if tt.expected.err != nil {
|
||||||
|
assert.Equal(t, tt.expected.err.Error(), err.Error())
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user