1
0
mirror of https://github.com/rancher/norman.git synced 2025-06-20 20:52:01 +00:00
norman/clientbase/object_client.go

191 lines
4.8 KiB
Go
Raw Normal View History

2017-11-11 04:44:02 +00:00
package clientbase
import (
"encoding/json"
"github.com/pkg/errors"
2017-12-05 16:21:12 +00:00
"k8s.io/apimachinery/pkg/api/meta"
2017-11-11 04:44:02 +00:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/rest"
)
type ObjectFactory interface {
Object() runtime.Object
List() runtime.Object
}
type ObjectClient struct {
restClient rest.Interface
resource *metav1.APIResource
gvk schema.GroupVersionKind
ns string
Factory ObjectFactory
}
2017-11-13 19:50:25 +00:00
func NewObjectClient(namespace string, restClient rest.Interface, apiResource *metav1.APIResource, gvk schema.GroupVersionKind, factory ObjectFactory) *ObjectClient {
2017-11-11 04:44:02 +00:00
return &ObjectClient{
restClient: restClient,
resource: apiResource,
gvk: gvk,
ns: namespace,
Factory: factory,
2017-11-13 19:50:25 +00:00
}
2017-11-11 04:44:02 +00:00
}
2017-11-14 20:46:34 +00:00
func (p *ObjectClient) getAPIPrefix() string {
if p.gvk.Group == "" {
return "api"
}
return "apis"
}
2017-11-11 04:44:02 +00:00
func (p *ObjectClient) Create(o runtime.Object) (runtime.Object, error) {
ns := p.ns
if obj, ok := o.(metav1.Object); ok && obj.GetNamespace() != "" {
ns = obj.GetNamespace()
}
2017-12-05 16:21:12 +00:00
if t, err := meta.TypeAccessor(o); err == nil {
if t.GetKind() == "" {
t.SetKind(p.gvk.Kind)
}
if t.GetAPIVersion() == "" {
apiVersion, _ := p.gvk.ToAPIVersionAndKind()
t.SetAPIVersion(apiVersion)
}
}
2017-11-11 04:44:02 +00:00
result := p.Factory.Object()
err := p.restClient.Post().
2017-11-14 20:46:34 +00:00
Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version).
2017-11-11 04:44:02 +00:00
NamespaceIfScoped(ns, p.resource.Namespaced).
Resource(p.resource.Name).
Body(o).
Do().
Into(result)
return result, err
}
func (p *ObjectClient) Get(name string, opts metav1.GetOptions) (runtime.Object, error) {
result := p.Factory.Object()
err := p.restClient.Get().
2017-11-14 20:46:34 +00:00
Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version).
2017-11-11 04:44:02 +00:00
NamespaceIfScoped(p.ns, p.resource.Namespaced).
Resource(p.resource.Name).
VersionedParams(&opts, dynamic.VersionedParameterEncoderWithV1Fallback).
Name(name).
Do().
Into(result)
return result, err
}
func (p *ObjectClient) Update(name string, o runtime.Object) (runtime.Object, error) {
ns := p.ns
if obj, ok := o.(metav1.Object); ok && obj.GetNamespace() != "" {
ns = obj.GetNamespace()
}
result := p.Factory.Object()
if len(name) == 0 {
return result, errors.New("object missing name")
}
err := p.restClient.Put().
2017-11-14 20:46:34 +00:00
Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version).
2017-11-11 04:44:02 +00:00
NamespaceIfScoped(ns, p.resource.Namespaced).
Resource(p.resource.Name).
Name(name).
Body(o).
Do().
Into(result)
return result, err
}
func (p *ObjectClient) Delete(name string, opts *metav1.DeleteOptions) error {
return p.restClient.Delete().
2017-11-14 20:46:34 +00:00
Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version).
2017-11-11 04:44:02 +00:00
NamespaceIfScoped(p.ns, p.resource.Namespaced).
Resource(p.resource.Name).
Name(name).
Body(opts).
Do().
Error()
}
func (p *ObjectClient) List(opts metav1.ListOptions) (runtime.Object, error) {
result := p.Factory.List()
return result, p.restClient.Get().
2017-11-14 20:46:34 +00:00
Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version).
2017-11-11 04:44:02 +00:00
NamespaceIfScoped(p.ns, p.resource.Namespaced).
Resource(p.resource.Name).
VersionedParams(&opts, dynamic.VersionedParameterEncoderWithV1Fallback).
Do().
Into(result)
}
func (p *ObjectClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
r, err := p.restClient.Get().
2017-11-14 20:46:34 +00:00
Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version).
2017-11-11 04:44:02 +00:00
Prefix("watch").
NamespaceIfScoped(p.ns, p.resource.Namespaced).
Resource(p.resource.Name).
VersionedParams(&opts, dynamic.VersionedParameterEncoderWithV1Fallback).
Stream()
if err != nil {
return nil, err
}
return watch.NewStreamWatcher(&dynamicDecoder{
factory: p.Factory,
dec: json.NewDecoder(r),
close: r.Close,
}), nil
}
func (p *ObjectClient) DeleteCollection(deleteOptions *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
return p.restClient.Delete().
2017-11-14 20:46:34 +00:00
Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version).
2017-11-11 04:44:02 +00:00
NamespaceIfScoped(p.ns, p.resource.Namespaced).
Resource(p.resource.Name).
VersionedParams(&listOptions, dynamic.VersionedParameterEncoderWithV1Fallback).
Body(deleteOptions).
Do().
Error()
}
type dynamicDecoder struct {
factory ObjectFactory
dec *json.Decoder
close func() error
}
func (d *dynamicDecoder) Close() {
d.close()
}
func (d *dynamicDecoder) Decode() (action watch.EventType, object runtime.Object, err error) {
e := dynamicEvent{
Object: holder{
factory: d.factory,
},
}
if err := d.dec.Decode(&e); err != nil {
return watch.Error, nil, err
}
return e.Type, e.Object.obj, nil
}
type dynamicEvent struct {
Type watch.EventType
Object holder
}
type holder struct {
factory ObjectFactory
obj runtime.Object
}
func (h *holder) UnmarshalJSON(b []byte) error {
h.obj = h.factory.Object()
return json.Unmarshal(b, h.obj)
}