Commit 82e32d2a authored by David Eads's avatar David Eads

add subresource support for the dynamic client

parent 1fd4149e
...@@ -77,24 +77,6 @@ func NewNamespacedCustomResourceClient(ns string, client dynamic.DynamicInterfac ...@@ -77,24 +77,6 @@ func NewNamespacedCustomResourceClient(ns string, client dynamic.DynamicInterfac
return client.Resource(gvr) return client.Resource(gvr)
} }
func NewNamespacedCustomResourceStatusClient(ns string, client dynamic.DynamicInterface, crd *apiextensionsv1beta1.CustomResourceDefinition) dynamic.DynamicResourceInterface {
gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Spec.Names.Plural}
if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped {
return client.NamespacedSubresource(gvr, "status", ns)
}
return client.ClusterSubresource(gvr, "status")
}
func NewNamespacedCustomResourceScaleClient(ns string, client dynamic.DynamicInterface, crd *apiextensionsv1beta1.CustomResourceDefinition) dynamic.DynamicResourceInterface {
gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Spec.Names.Plural}
if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped {
return client.NamespacedSubresource(gvr, "scale", ns)
}
return client.ClusterSubresource(gvr, "scale")
}
func TestMultipleResourceInstances(t *testing.T) { func TestMultipleResourceInstances(t *testing.T) {
stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients() stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients()
if err != nil { if err != nil {
......
...@@ -105,7 +105,6 @@ func TestStatusSubresource(t *testing.T) { ...@@ -105,7 +105,6 @@ func TestStatusSubresource(t *testing.T) {
ns := "not-the-default" ns := "not-the-default"
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, dynamicClient, noxuDefinition)
_, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition) _, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition)
if err != nil { if err != nil {
t.Fatalf("unable to create noxu instance: %v", err) t.Fatalf("unable to create noxu instance: %v", err)
...@@ -135,7 +134,7 @@ func TestStatusSubresource(t *testing.T) { ...@@ -135,7 +134,7 @@ func TestStatusSubresource(t *testing.T) {
// UpdateStatus should not update spec. // UpdateStatus should not update spec.
// Check that .spec.num = 10 and .status.num = 20 // Check that .spec.num = 10 and .status.num = 20
updatedStatusInstance, err := noxuStatusResourceClient.Update(gottenNoxuInstance) updatedStatusInstance, err := noxuResourceClient.UpdateStatus(gottenNoxuInstance)
if err != nil { if err != nil {
t.Fatalf("unable to update status: %v", err) t.Fatalf("unable to update status: %v", err)
} }
...@@ -238,7 +237,6 @@ func TestScaleSubresource(t *testing.T) { ...@@ -238,7 +237,6 @@ func TestScaleSubresource(t *testing.T) {
ns := "not-the-default" ns := "not-the-default"
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, dynamicClient, noxuDefinition)
_, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition) _, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition)
if err != nil { if err != nil {
t.Fatalf("unable to create noxu instance: %v", err) t.Fatalf("unable to create noxu instance: %v", err)
...@@ -258,7 +256,7 @@ func TestScaleSubresource(t *testing.T) { ...@@ -258,7 +256,7 @@ func TestScaleSubresource(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
_, err = noxuStatusResourceClient.Update(gottenNoxuInstance) _, err = noxuResourceClient.UpdateStatus(gottenNoxuInstance)
if err != nil { if err != nil {
t.Fatalf("unable to update status: %v", err) t.Fatalf("unable to update status: %v", err)
} }
...@@ -430,7 +428,6 @@ func TestValidateOnlyStatus(t *testing.T) { ...@@ -430,7 +428,6 @@ func TestValidateOnlyStatus(t *testing.T) {
} }
ns := "not-the-default" ns := "not-the-default"
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, dynamicClient, noxuDefinition)
// set .spec.num = 10 and .status.num = 10 // set .spec.num = 10 and .status.num = 10
noxuInstance := NewNoxuSubresourceInstance(ns, "foo") noxuInstance := NewNoxuSubresourceInstance(ns, "foo")
...@@ -449,7 +446,7 @@ func TestValidateOnlyStatus(t *testing.T) { ...@@ -449,7 +446,7 @@ func TestValidateOnlyStatus(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unexpected error setting .spec.num: %v", err) t.Fatalf("unexpected error setting .spec.num: %v", err)
} }
createdNoxuInstance, err = noxuStatusResourceClient.Update(createdNoxuInstance) createdNoxuInstance, err = noxuResourceClient.UpdateStatus(createdNoxuInstance)
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
...@@ -459,7 +456,7 @@ func TestValidateOnlyStatus(t *testing.T) { ...@@ -459,7 +456,7 @@ func TestValidateOnlyStatus(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unexpected error setting .status.num: %v", err) t.Fatalf("unexpected error setting .status.num: %v", err)
} }
createdNoxuInstance, err = noxuStatusResourceClient.Update(createdNoxuInstance) createdNoxuInstance, err = noxuResourceClient.UpdateStatus(createdNoxuInstance)
if err == nil { if err == nil {
t.Fatal("expected error, but got none") t.Fatal("expected error, but got none")
} }
...@@ -577,7 +574,6 @@ func TestGeneration(t *testing.T) { ...@@ -577,7 +574,6 @@ func TestGeneration(t *testing.T) {
ns := "not-the-default" ns := "not-the-default"
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, dynamicClient, noxuDefinition)
_, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition) _, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition)
if err != nil { if err != nil {
t.Fatalf("unable to create noxu instance: %v", err) t.Fatalf("unable to create noxu instance: %v", err)
...@@ -599,7 +595,7 @@ func TestGeneration(t *testing.T) { ...@@ -599,7 +595,7 @@ func TestGeneration(t *testing.T) {
} }
// UpdateStatus does not increment generation // UpdateStatus does not increment generation
updatedStatusInstance, err := noxuStatusResourceClient.Update(gottenNoxuInstance) updatedStatusInstance, err := noxuResourceClient.UpdateStatus(gottenNoxuInstance)
if err != nil { if err != nil {
t.Fatalf("unable to update status: %v", err) t.Fatalf("unable to update status: %v", err)
} }
...@@ -660,8 +656,6 @@ func TestSubresourcePatch(t *testing.T) { ...@@ -660,8 +656,6 @@ func TestSubresourcePatch(t *testing.T) {
ns := "not-the-default" ns := "not-the-default"
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition) noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, dynamicClient, noxuDefinition)
noxuScaleResourceClient := NewNamespacedCustomResourceScaleClient(ns, dynamicClient, noxuDefinition)
_, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition) _, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition)
if err != nil { if err != nil {
t.Fatalf("unable to create noxu instance: %v", err) t.Fatalf("unable to create noxu instance: %v", err)
...@@ -673,7 +667,7 @@ func TestSubresourcePatch(t *testing.T) { ...@@ -673,7 +667,7 @@ func TestSubresourcePatch(t *testing.T) {
} }
patch := []byte(`{"spec": {"num":999}, "status": {"num":999}}`) patch := []byte(`{"spec": {"num":999}, "status": {"num":999}}`)
patchedNoxuInstance, err := noxuStatusResourceClient.Patch("foo", types.MergePatchType, patch) patchedNoxuInstance, err := noxuResourceClient.Patch("foo", types.MergePatchType, patch, "status")
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
...@@ -708,19 +702,19 @@ func TestSubresourcePatch(t *testing.T) { ...@@ -708,19 +702,19 @@ func TestSubresourcePatch(t *testing.T) {
} }
// no-op patch // no-op patch
_, err = noxuStatusResourceClient.Patch("foo", types.MergePatchType, patch) _, err = noxuResourceClient.Patch("foo", types.MergePatchType, patch, "status")
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
// empty patch // empty patch
_, err = noxuStatusResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`)) _, err = noxuResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`), "status")
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
patch = []byte(`{"spec": {"replicas":7}, "status": {"replicas":7}}`) patch = []byte(`{"spec": {"replicas":7}, "status": {"replicas":7}}`)
patchedNoxuInstance, err = noxuScaleResourceClient.Patch("foo", types.MergePatchType, patch) patchedNoxuInstance, err = noxuResourceClient.Patch("foo", types.MergePatchType, patch, "scale")
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
...@@ -749,24 +743,24 @@ func TestSubresourcePatch(t *testing.T) { ...@@ -749,24 +743,24 @@ func TestSubresourcePatch(t *testing.T) {
} }
// no-op patch // no-op patch
_, err = noxuScaleResourceClient.Patch("foo", types.MergePatchType, patch) _, err = noxuResourceClient.Patch("foo", types.MergePatchType, patch, "scale")
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
// empty patch // empty patch
_, err = noxuScaleResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`)) _, err = noxuResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`), "scale")
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
// make sure strategic merge patch is not supported for both status and scale // make sure strategic merge patch is not supported for both status and scale
_, err = noxuStatusResourceClient.Patch("foo", types.StrategicMergePatchType, patch) _, err = noxuResourceClient.Patch("foo", types.StrategicMergePatchType, patch, "status")
if err == nil { if err == nil {
t.Fatalf("unexpected non-error: strategic merge patch is not supported for custom resources") t.Fatalf("unexpected non-error: strategic merge patch is not supported for custom resources")
} }
_, err = noxuScaleResourceClient.Patch("foo", types.StrategicMergePatchType, patch) _, err = noxuResourceClient.Patch("foo", types.StrategicMergePatchType, patch, "scale")
if err == nil { if err == nil {
t.Fatalf("unexpected non-error: strategic merge patch is not supported for custom resources") t.Fatalf("unexpected non-error: strategic merge patch is not supported for custom resources")
} }
......
...@@ -17,7 +17,6 @@ limitations under the License. ...@@ -17,7 +17,6 @@ limitations under the License.
package dynamic package dynamic
import ( import (
"fmt"
"io" "io"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
...@@ -33,20 +32,15 @@ import ( ...@@ -33,20 +32,15 @@ import (
type DynamicInterface interface { type DynamicInterface interface {
Resource(resource schema.GroupVersionResource) NamespaceableDynamicResourceInterface Resource(resource schema.GroupVersionResource) NamespaceableDynamicResourceInterface
// Deprecated, this isn't how we want to do it
ClusterSubresource(resource schema.GroupVersionResource, subresource string) DynamicResourceInterface
// Deprecated, this isn't how we want to do it
NamespacedSubresource(resource schema.GroupVersionResource, subresource, namespace string) DynamicResourceInterface
} }
type DynamicResourceInterface interface { type DynamicResourceInterface interface {
Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) Create(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error)
Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) Update(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error)
UpdateStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) UpdateStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error)
Delete(name string, options *metav1.DeleteOptions) error Delete(name string, options *metav1.DeleteOptions, subresources ...string) error
DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
Get(name string, options metav1.GetOptions) (*unstructured.Unstructured, error) Get(name string, options metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error)
List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error)
Watch(opts metav1.ListOptions) (watch.Interface, error) Watch(opts metav1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*unstructured.Unstructured, error) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*unstructured.Unstructured, error)
...@@ -84,40 +78,36 @@ func NewForConfig(inConfig *rest.Config) (DynamicInterface, error) { ...@@ -84,40 +78,36 @@ func NewForConfig(inConfig *rest.Config) (DynamicInterface, error) {
} }
type dynamicResourceClient struct { type dynamicResourceClient struct {
client *dynamicClient client *dynamicClient
namespace string namespace string
resource schema.GroupVersionResource resource schema.GroupVersionResource
subresource string
} }
func (c *dynamicClient) Resource(resource schema.GroupVersionResource) NamespaceableDynamicResourceInterface { func (c *dynamicClient) Resource(resource schema.GroupVersionResource) NamespaceableDynamicResourceInterface {
return &dynamicResourceClient{client: c, resource: resource} return &dynamicResourceClient{client: c, resource: resource}
} }
func (c *dynamicClient) ClusterSubresource(resource schema.GroupVersionResource, subresource string) DynamicResourceInterface {
return &dynamicResourceClient{client: c, resource: resource, subresource: subresource}
}
func (c *dynamicClient) NamespacedSubresource(resource schema.GroupVersionResource, subresource, namespace string) DynamicResourceInterface {
return &dynamicResourceClient{client: c, resource: resource, namespace: namespace, subresource: subresource}
}
func (c *dynamicResourceClient) Namespace(ns string) DynamicResourceInterface { func (c *dynamicResourceClient) Namespace(ns string) DynamicResourceInterface {
ret := *c ret := *c
ret.namespace = ns ret.namespace = ns
return &ret return &ret
} }
func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) {
if len(c.subresource) > 0 {
return nil, fmt.Errorf("create not supported for subresources")
}
outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj) outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
if err != nil { if err != nil {
return nil, err return nil, err
} }
name := ""
if len(subresources) > 0 {
accessor, err := meta.Accessor(obj)
if err != nil {
return nil, err
}
name = accessor.GetName()
}
result := c.client.client.Post().AbsPath(c.makeURLSegments("")...).Body(outBytes).Do() result := c.client.client.Post().AbsPath(append(c.makeURLSegments(name), subresources...)...).Body(outBytes).Do()
if err := result.Error(); err != nil { if err := result.Error(); err != nil {
return nil, err return nil, err
} }
...@@ -133,7 +123,7 @@ func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured) (*unstruc ...@@ -133,7 +123,7 @@ func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured) (*unstruc
return uncastObj.(*unstructured.Unstructured), nil return uncastObj.(*unstructured.Unstructured), nil
} }
func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) { func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) {
accessor, err := meta.Accessor(obj) accessor, err := meta.Accessor(obj)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -143,7 +133,7 @@ func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured) (*unstruc ...@@ -143,7 +133,7 @@ func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured) (*unstruc
return nil, err return nil, err
} }
result := c.client.client.Put().AbsPath(c.makeURLSegments(accessor.GetName())...).Body(outBytes).Do() result := c.client.client.Put().AbsPath(append(c.makeURLSegments(accessor.GetName()), subresources...)...).Body(outBytes).Do()
if err := result.Error(); err != nil { if err := result.Error(); err != nil {
return nil, err return nil, err
} }
...@@ -182,7 +172,7 @@ func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured) (*u ...@@ -182,7 +172,7 @@ func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured) (*u
return uncastObj.(*unstructured.Unstructured), nil return uncastObj.(*unstructured.Unstructured), nil
} }
func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions) error { func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions, subresources ...string) error {
if opts == nil { if opts == nil {
opts = &metav1.DeleteOptions{} opts = &metav1.DeleteOptions{}
} }
...@@ -191,15 +181,11 @@ func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions) ...@@ -191,15 +181,11 @@ func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions)
return err return err
} }
result := c.client.client.Delete().AbsPath(c.makeURLSegments(name)...).Body(deleteOptionsByte).Do() result := c.client.client.Delete().AbsPath(append(c.makeURLSegments(name), subresources...)...).Body(deleteOptionsByte).Do()
return result.Error() return result.Error()
} }
func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error { func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
if len(c.subresource) > 0 {
return fmt.Errorf("deletecollection not supported for subresources")
}
if opts == nil { if opts == nil {
opts = &metav1.DeleteOptions{} opts = &metav1.DeleteOptions{}
} }
...@@ -212,8 +198,8 @@ func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, lis ...@@ -212,8 +198,8 @@ func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, lis
return result.Error() return result.Error()
} }
func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) { func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) {
result := c.client.client.Get().AbsPath(c.makeURLSegments(name)...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do() result := c.client.client.Get().AbsPath(append(c.makeURLSegments(name), subresources...)...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do()
if err := result.Error(); err != nil { if err := result.Error(); err != nil {
return nil, err return nil, err
} }
...@@ -229,10 +215,6 @@ func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions) (*unstr ...@@ -229,10 +215,6 @@ func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions) (*unstr
} }
func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) { func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
if len(c.subresource) > 0 {
return nil, fmt.Errorf("list not supported for subresources")
}
result := c.client.client.Get().AbsPath(c.makeURLSegments("")...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do() result := c.client.client.Get().AbsPath(c.makeURLSegments("")...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do()
if err := result.Error(); err != nil { if err := result.Error(); err != nil {
return nil, err return nil, err
...@@ -257,10 +239,6 @@ func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.Uns ...@@ -257,10 +239,6 @@ func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.Uns
} }
func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
if len(c.subresource) > 0 {
return nil, fmt.Errorf("watch not supported for subresources")
}
internalGV := schema.GroupVersions{ internalGV := schema.GroupVersions{
{Group: c.resource.Group, Version: runtime.APIVersionInternal}, {Group: c.resource.Group, Version: runtime.APIVersionInternal},
// always include the legacy group as a decoding target to handle non-error `Status` return types // always include the legacy group as a decoding target to handle non-error `Status` return types
...@@ -320,15 +298,6 @@ func (c *dynamicResourceClient) makeURLSegments(name string) []string { ...@@ -320,15 +298,6 @@ func (c *dynamicResourceClient) makeURLSegments(name string) []string {
if len(name) > 0 { if len(name) > 0 {
url = append(url, name) url = append(url, name)
// subresources only work on things with names
if len(c.subresource) > 0 {
url = append(url, c.subresource)
}
} else {
if len(c.subresource) > 0 {
panic("somehow snuck a subresource and an empty name. programmer error")
}
} }
return url return url
......
...@@ -225,6 +225,16 @@ func NewRootDeleteAction(resource schema.GroupVersionResource, name string) Dele ...@@ -225,6 +225,16 @@ func NewRootDeleteAction(resource schema.GroupVersionResource, name string) Dele
return action return action
} }
func NewRootDeleteSubresourceAction(resource schema.GroupVersionResource, subresource string, name string) DeleteActionImpl {
action := DeleteActionImpl{}
action.Verb = "delete"
action.Resource = resource
action.Subresource = subresource
action.Name = name
return action
}
func NewDeleteAction(resource schema.GroupVersionResource, namespace, name string) DeleteActionImpl { func NewDeleteAction(resource schema.GroupVersionResource, namespace, name string) DeleteActionImpl {
action := DeleteActionImpl{} action := DeleteActionImpl{}
action.Verb = "delete" action.Verb = "delete"
...@@ -235,6 +245,17 @@ func NewDeleteAction(resource schema.GroupVersionResource, namespace, name strin ...@@ -235,6 +245,17 @@ func NewDeleteAction(resource schema.GroupVersionResource, namespace, name strin
return action return action
} }
func NewDeleteSubresourceAction(resource schema.GroupVersionResource, subresource, namespace, name string) DeleteActionImpl {
action := DeleteActionImpl{}
action.Verb = "delete"
action.Resource = resource
action.Subresource = subresource
action.Namespace = namespace
action.Name = name
return action
}
func NewRootDeleteCollectionAction(resource schema.GroupVersionResource, opts interface{}) DeleteCollectionActionImpl { func NewRootDeleteCollectionAction(resource schema.GroupVersionResource, opts interface{}) DeleteCollectionActionImpl {
action := DeleteCollectionActionImpl{} action := DeleteCollectionActionImpl{}
action.Verb = "delete-collection" action.Verb = "delete-collection"
......
...@@ -150,14 +150,12 @@ func TestCRD(t *testing.T) { ...@@ -150,14 +150,12 @@ func TestCRD(t *testing.T) {
} }
t.Logf("Trying to access foos.cr.bar.com with dynamic client") t.Logf("Trying to access foos.cr.bar.com with dynamic client")
barComConfig := *result.ClientConfig dynamicClient, err := dynamic.NewForConfig(result.ClientConfig)
barComConfig.GroupVersion = &schema.GroupVersion{Group: "cr.bar.com", Version: "v1"}
barComConfig.APIPath = "/apis"
barComClient, err := dynamic.NewClient(&barComConfig, *barComConfig.GroupVersion)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
_, err = barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").List(metav1.ListOptions{}) fooResource := schema.GroupVersionResource{Group: "cr.bar.com", Version: "v1", Resource: "foos"}
_, err = dynamicClient.Resource(fooResource).Namespace("default").List(metav1.ListOptions{})
if err != nil { if err != nil {
t.Errorf("Failed to list foos.cr.bar.com instances: %v", err) t.Errorf("Failed to list foos.cr.bar.com instances: %v", err)
} }
...@@ -201,7 +199,7 @@ func TestCRD(t *testing.T) { ...@@ -201,7 +199,7 @@ func TestCRD(t *testing.T) {
} }
createErr := make(chan error, 1) createErr := make(chan error, 1)
go func() { go func() {
_, err := barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Create(unstructuredFoo) _, err := dynamicClient.Resource(fooResource).Namespace("default").Create(unstructuredFoo)
t.Logf("Foo instance create returned: %v", err) t.Logf("Foo instance create returned: %v", err)
if err != nil { if err != nil {
createErr <- err createErr <- err
...@@ -216,7 +214,7 @@ func TestCRD(t *testing.T) { ...@@ -216,7 +214,7 @@ func TestCRD(t *testing.T) {
} }
t.Logf("Checking that Foo instance is visible with IncludeUninitialized=true") t.Logf("Checking that Foo instance is visible with IncludeUninitialized=true")
_, err := barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Get(foo.ObjectMeta.Name, metav1.GetOptions{ _, err := dynamicClient.Resource(fooResource).Namespace("default").Get(foo.ObjectMeta.Name, metav1.GetOptions{
IncludeUninitialized: true, IncludeUninitialized: true,
}) })
switch { switch {
...@@ -237,7 +235,7 @@ func TestCRD(t *testing.T) { ...@@ -237,7 +235,7 @@ func TestCRD(t *testing.T) {
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
// would love to replace the following with a patch, but removing strings from the intitializer array // would love to replace the following with a patch, but removing strings from the intitializer array
// is not what JSON (Merge) patch authors had in mind. // is not what JSON (Merge) patch authors had in mind.
fooUnstructured, err := barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Get(foo.ObjectMeta.Name, metav1.GetOptions{ fooUnstructured, err := dynamicClient.Resource(fooResource).Namespace("default").Get(foo.ObjectMeta.Name, metav1.GetOptions{
IncludeUninitialized: true, IncludeUninitialized: true,
}) })
if err != nil { if err != nil {
...@@ -274,7 +272,7 @@ func TestCRD(t *testing.T) { ...@@ -274,7 +272,7 @@ func TestCRD(t *testing.T) {
} }
fooUnstructured.UnmarshalJSON(bs) fooUnstructured.UnmarshalJSON(bs)
_, err = barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Update(fooUnstructured) _, err = dynamicClient.Resource(fooResource).Namespace("default").Update(fooUnstructured)
if err != nil && !errors.IsConflict(err) { if err != nil && !errors.IsConflict(err) {
t.Fatalf("Failed to update Foo instance: %v", err) t.Fatalf("Failed to update Foo instance: %v", err)
} else if err == nil { } else if err == nil {
...@@ -287,7 +285,7 @@ func TestCRD(t *testing.T) { ...@@ -287,7 +285,7 @@ func TestCRD(t *testing.T) {
} }
t.Logf("Checking that Foo instance is visible after removing the initializer") t.Logf("Checking that Foo instance is visible after removing the initializer")
if _, err := barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Get(foo.ObjectMeta.Name, metav1.GetOptions{}); err != nil { if _, err := dynamicClient.Resource(fooResource).Namespace("default").Get(foo.ObjectMeta.Name, metav1.GetOptions{}); err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment