k3s/vendor/github.com/rancher/wrangler/pkg/apply/apply.go

284 lines
7.6 KiB
Go
Raw Normal View History

2019-05-09 22:03:45 +00:00
package apply
import (
2020-03-26 21:07:15 +00:00
"context"
2019-05-09 22:03:45 +00:00
"fmt"
"sync"
"github.com/rancher/wrangler/pkg/apply/injectors"
"github.com/rancher/wrangler/pkg/objectset"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/discovery"
"k8s.io/client-go/dynamic"
2019-09-05 18:55:53 +00:00
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
2019-05-09 22:03:45 +00:00
"k8s.io/client-go/tools/cache"
)
const (
defaultNamespace = "default"
)
type Patcher func(namespace, name string, pt types.PatchType, data []byte) (runtime.Object, error)
2019-12-12 01:27:03 +00:00
// return false if the Reconciler did not handler this object
type Reconciler func(oldObj runtime.Object, newObj runtime.Object) (bool, error)
type ClientFactory func(gvr schema.GroupVersionResource) (dynamic.NamespaceableResourceInterface, error)
2019-05-09 22:03:45 +00:00
2020-04-22 22:34:19 +00:00
type InformerFactory interface {
Get(gvk schema.GroupVersionKind, gvr schema.GroupVersionResource) (cache.SharedIndexInformer, error)
}
2019-05-09 22:03:45 +00:00
type InformerGetter interface {
Informer() cache.SharedIndexInformer
GroupVersionKind() schema.GroupVersionKind
}
2020-04-22 22:34:19 +00:00
type PatchByGVK map[schema.GroupVersionKind]map[objectset.ObjectKey]string
func (p PatchByGVK) Add(gvk schema.GroupVersionKind, namespace, name, patch string) {
d, ok := p[gvk]
if !ok {
d = map[objectset.ObjectKey]string{}
p[gvk] = d
}
d[objectset.ObjectKey{
Name: name,
Namespace: namespace,
}] = patch
}
type Plan struct {
Create objectset.ObjectKeyByGVK
Delete objectset.ObjectKeyByGVK
Update PatchByGVK
Objects []runtime.Object
}
2019-05-09 22:03:45 +00:00
type Apply interface {
Apply(set *objectset.ObjectSet) error
ApplyObjects(objs ...runtime.Object) error
2020-03-26 21:07:15 +00:00
WithContext(ctx context.Context) Apply
2019-05-09 22:03:45 +00:00
WithCacheTypes(igs ...InformerGetter) Apply
2020-04-22 22:34:19 +00:00
WithCacheTypeFactory(factory InformerFactory) Apply
2019-05-09 22:03:45 +00:00
WithSetID(id string) Apply
WithOwner(obj runtime.Object) Apply
2020-04-22 22:34:19 +00:00
WithOwnerKey(key string, gvk schema.GroupVersionKind) Apply
2019-05-09 22:03:45 +00:00
WithInjector(injs ...injectors.ConfigInjector) Apply
WithInjectorName(injs ...string) Apply
WithPatcher(gvk schema.GroupVersionKind, patchers Patcher) Apply
2019-12-12 01:27:03 +00:00
WithReconciler(gvk schema.GroupVersionKind, reconciler Reconciler) Apply
2019-05-09 22:03:45 +00:00
WithStrictCaching() Apply
2019-12-12 01:27:03 +00:00
WithDynamicLookup() Apply
WithRestrictClusterScoped() Apply
2019-05-09 22:03:45 +00:00
WithDefaultNamespace(ns string) Apply
2019-09-05 18:55:53 +00:00
WithListerNamespace(ns string) Apply
2019-05-09 22:03:45 +00:00
WithRateLimiting(ratelimitingQps float32) Apply
WithNoDelete() Apply
2019-12-12 01:27:03 +00:00
WithGVK(gvks ...schema.GroupVersionKind) Apply
WithSetOwnerReference(controller, block bool) Apply
2020-04-22 22:34:19 +00:00
FindOwner(obj runtime.Object) (runtime.Object, error)
PurgeOrphan(obj runtime.Object) error
DryRun(objs ...runtime.Object) (Plan, error)
2019-05-09 22:03:45 +00:00
}
2019-09-05 18:55:53 +00:00
func NewForConfig(cfg *rest.Config) (Apply, error) {
k8s, err := kubernetes.NewForConfig(cfg)
if err != nil {
return nil, err
}
return New(k8s.Discovery(), NewClientFactory(cfg)), nil
}
2019-05-09 22:03:45 +00:00
func New(discovery discovery.DiscoveryInterface, cf ClientFactory, igs ...InformerGetter) Apply {
a := &apply{
clients: &clients{
clientFactory: cf,
discovery: discovery,
namespaced: map[schema.GroupVersionKind]bool{},
2020-04-22 22:34:19 +00:00
gvkToGVR: map[schema.GroupVersionKind]schema.GroupVersionResource{},
2019-05-09 22:03:45 +00:00
clients: map[schema.GroupVersionKind]dynamic.NamespaceableResourceInterface{},
},
informers: map[schema.GroupVersionKind]cache.SharedIndexInformer{},
}
for _, ig := range igs {
a.informers[ig.GroupVersionKind()] = ig.Informer()
}
return a
}
type apply struct {
clients *clients
informers map[schema.GroupVersionKind]cache.SharedIndexInformer
}
type clients struct {
sync.Mutex
clientFactory ClientFactory
discovery discovery.DiscoveryInterface
namespaced map[schema.GroupVersionKind]bool
2020-04-22 22:34:19 +00:00
gvkToGVR map[schema.GroupVersionKind]schema.GroupVersionResource
2019-05-09 22:03:45 +00:00
clients map[schema.GroupVersionKind]dynamic.NamespaceableResourceInterface
}
func (c *clients) IsNamespaced(gvk schema.GroupVersionKind) bool {
c.Lock()
defer c.Unlock()
return c.namespaced[gvk]
}
2020-04-22 22:34:19 +00:00
func (c *clients) gvr(gvk schema.GroupVersionKind) schema.GroupVersionResource {
c.Lock()
defer c.Unlock()
return c.gvkToGVR[gvk]
}
2019-05-09 22:03:45 +00:00
func (c *clients) client(gvk schema.GroupVersionKind) (dynamic.NamespaceableResourceInterface, error) {
c.Lock()
defer c.Unlock()
if client, ok := c.clients[gvk]; ok {
return client, nil
}
resources, err := c.discovery.ServerResourcesForGroupVersion(gvk.GroupVersion().String())
if err != nil {
return nil, err
}
for _, resource := range resources.APIResources {
if resource.Kind != gvk.Kind {
continue
}
2019-12-12 01:27:03 +00:00
client, err := c.clientFactory(gvk.GroupVersion().WithResource(resource.Name))
2019-05-09 22:03:45 +00:00
if err != nil {
return nil, err
}
c.namespaced[gvk] = resource.Namespaced
c.clients[gvk] = client
2020-04-22 22:34:19 +00:00
c.gvkToGVR[gvk] = gvk.GroupVersion().WithResource(resource.Name)
2019-05-09 22:03:45 +00:00
return client, nil
}
return nil, fmt.Errorf("failed to discover client for %s", gvk)
}
func (a *apply) newDesiredSet() desiredSet {
return desiredSet{
a: a,
defaultNamespace: defaultNamespace,
2020-03-26 21:07:15 +00:00
ctx: context.Background(),
2019-05-09 22:03:45 +00:00
ratelimitingQps: 1,
2019-12-12 01:27:03 +00:00
reconcilers: defaultReconcilers,
strictCaching: true,
2019-05-09 22:03:45 +00:00
}
}
2020-04-22 22:34:19 +00:00
func (a *apply) DryRun(objs ...runtime.Object) (Plan, error) {
return a.newDesiredSet().DryRun(objs...)
}
2019-05-09 22:03:45 +00:00
func (a *apply) Apply(set *objectset.ObjectSet) error {
return a.newDesiredSet().Apply(set)
}
func (a *apply) ApplyObjects(objs ...runtime.Object) error {
os := objectset.NewObjectSet()
os.Add(objs...)
return a.newDesiredSet().Apply(os)
}
func (a *apply) WithSetID(id string) Apply {
return a.newDesiredSet().WithSetID(id)
}
func (a *apply) WithOwner(obj runtime.Object) Apply {
return a.newDesiredSet().WithOwner(obj)
}
2020-04-22 22:34:19 +00:00
func (a *apply) WithOwnerKey(key string, gvk schema.GroupVersionKind) Apply {
return a.newDesiredSet().WithOwnerKey(key, gvk)
}
2019-05-09 22:03:45 +00:00
func (a *apply) WithInjector(injs ...injectors.ConfigInjector) Apply {
return a.newDesiredSet().WithInjector(injs...)
}
func (a *apply) WithInjectorName(injs ...string) Apply {
return a.newDesiredSet().WithInjectorName(injs...)
}
func (a *apply) WithCacheTypes(igs ...InformerGetter) Apply {
return a.newDesiredSet().WithCacheTypes(igs...)
}
2020-04-22 22:34:19 +00:00
func (a *apply) WithCacheTypeFactory(factory InformerFactory) Apply {
return a.newDesiredSet().WithCacheTypeFactory(factory)
}
2019-12-12 01:27:03 +00:00
func (a *apply) WithGVK(gvks ...schema.GroupVersionKind) Apply {
return a.newDesiredSet().WithGVK(gvks...)
}
2019-05-09 22:03:45 +00:00
func (a *apply) WithPatcher(gvk schema.GroupVersionKind, patcher Patcher) Apply {
return a.newDesiredSet().WithPatcher(gvk, patcher)
}
2019-12-12 01:27:03 +00:00
func (a *apply) WithReconciler(gvk schema.GroupVersionKind, reconciler Reconciler) Apply {
return a.newDesiredSet().WithReconciler(gvk, reconciler)
}
2019-05-09 22:03:45 +00:00
func (a *apply) WithStrictCaching() Apply {
return a.newDesiredSet().WithStrictCaching()
}
2019-12-12 01:27:03 +00:00
func (a *apply) WithDynamicLookup() Apply {
return a.newDesiredSet().WithDynamicLookup()
}
func (a *apply) WithRestrictClusterScoped() Apply {
return a.newDesiredSet().WithRestrictClusterScoped()
}
2019-05-09 22:03:45 +00:00
func (a *apply) WithDefaultNamespace(ns string) Apply {
return a.newDesiredSet().WithDefaultNamespace(ns)
}
2019-09-05 18:55:53 +00:00
func (a *apply) WithListerNamespace(ns string) Apply {
return a.newDesiredSet().WithListerNamespace(ns)
}
2019-05-09 22:03:45 +00:00
func (a *apply) WithRateLimiting(ratelimitingQps float32) Apply {
return a.newDesiredSet().WithRateLimiting(ratelimitingQps)
}
func (a *apply) WithNoDelete() Apply {
return a.newDesiredSet().WithNoDelete()
}
2019-12-12 01:27:03 +00:00
func (a *apply) WithSetOwnerReference(controller, block bool) Apply {
return a.newDesiredSet().WithSetOwnerReference(controller, block)
}
2020-03-26 21:07:15 +00:00
func (a *apply) WithContext(ctx context.Context) Apply {
return a.newDesiredSet().WithContext(ctx)
}
2020-04-22 22:34:19 +00:00
func (a *apply) FindOwner(obj runtime.Object) (runtime.Object, error) {
return a.newDesiredSet().FindOwner(obj)
}
func (a *apply) PurgeOrphan(obj runtime.Object) error {
return a.newDesiredSet().PurgeOrphan(obj)
}