From e832588662a3b1b4648f2d9b80c1d1c417d9c77d Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Fri, 1 Feb 2019 22:09:11 -0700 Subject: [PATCH] Add embedded service load balancer --- README.md | 10 + pkg/cli/cmds/server.go | 2 +- pkg/cli/server/server.go | 5 + pkg/server/server.go | 26 +- pkg/server/types.go | 7 +- pkg/servicelb/controller.go | 327 +++++++++++++ scripts/dev-server.sh | 2 +- types/apis/apps/v1/zz_generated_deepcopy.go | 39 ++ .../v1/zz_generated_deployment_controller.go | 441 ++++++++++++++++++ ..._generated_deployment_lifecycle_adapter.go | 63 +++ types/apis/apps/v1/zz_generated_k8s_client.go | 119 +++++ types/apis/apps/v1/zz_generated_scheme.go | 39 ++ types/apis/core/v1/zz_generated_deepcopy.go | 105 +++++ types/apis/core/v1/zz_generated_k8s_client.go | 159 +++++++ .../core/v1/zz_generated_node_controller.go | 440 +++++++++++++++++ .../v1/zz_generated_node_lifecycle_adapter.go | 63 +++ .../core/v1/zz_generated_pod_controller.go | 441 ++++++++++++++++++ .../v1/zz_generated_pod_lifecycle_adapter.go | 63 +++ types/apis/core/v1/zz_generated_scheme.go | 41 ++ .../v1/zz_generated_service_controller.go | 441 ++++++++++++++++++ .../zz_generated_service_lifecycle_adapter.go | 63 +++ types/codegen/main.go | 17 + 22 files changed, 2900 insertions(+), 13 deletions(-) create mode 100644 pkg/servicelb/controller.go create mode 100644 types/apis/apps/v1/zz_generated_deepcopy.go create mode 100644 types/apis/apps/v1/zz_generated_deployment_controller.go create mode 100644 types/apis/apps/v1/zz_generated_deployment_lifecycle_adapter.go create mode 100644 types/apis/apps/v1/zz_generated_k8s_client.go create mode 100644 types/apis/apps/v1/zz_generated_scheme.go create mode 100644 types/apis/core/v1/zz_generated_deepcopy.go create mode 100644 types/apis/core/v1/zz_generated_k8s_client.go create mode 100644 types/apis/core/v1/zz_generated_node_controller.go create mode 100644 types/apis/core/v1/zz_generated_node_lifecycle_adapter.go create mode 100644 types/apis/core/v1/zz_generated_pod_controller.go create mode 100644 types/apis/core/v1/zz_generated_pod_lifecycle_adapter.go create mode 100644 types/apis/core/v1/zz_generated_scheme.go create mode 100644 types/apis/core/v1/zz_generated_service_controller.go create mode 100644 types/apis/core/v1/zz_generated_service_lifecycle_adapter.go diff --git a/README.md b/README.md index 3e9dfbef6a..0c5fe527aa 100644 --- a/README.md +++ b/README.md @@ -231,6 +231,16 @@ CoreDNS is deployed on start of the agent, to disable add `--no-deploy coredns` If you don't install CoreDNS you will need to install a cluster DNS provider yourself. +Service Load Balancer +--------------------- + +k3s includes a basic service load balancer that uses available host ports. If you try to create +a load balancer that listens on port 80, for example, it will try to find a free host in the cluster +for port 80. If no port is available the load balancer will stay in Pending. + +To disable the embedded service load balancer (if you wish to use a different implementation like +MetalLB) just add `--no-deploy=servicelb` to the server on startup. + TODO ---- Currently broken or stuff that needs to be done for this to be considered production quality. diff --git a/pkg/cli/cmds/server.go b/pkg/cli/cmds/server.go index b90b809b64..cafc4bb3d3 100644 --- a/pkg/cli/cmds/server.go +++ b/pkg/cli/cmds/server.go @@ -66,7 +66,7 @@ func NewServerCommand(action func(*cli.Context) error) cli.Command { }, cli.StringSliceFlag{ Name: "no-deploy", - Usage: "Do not deploy packaged manifests (example: coredns)", + Usage: "Do not deploy packaged components (valid items: coredns, servicelb)", }, cli.StringFlag{ Name: "write-kubeconfig,o", diff --git a/pkg/cli/server/server.go b/pkg/cli/server/server.go index 901842801d..2af3badc1c 100644 --- a/pkg/cli/server/server.go +++ b/pkg/cli/server/server.go @@ -77,6 +77,11 @@ func run(app *cli.Context, cfg *cmds.Server) error { serverConfig.ControlConfig.NoLeaderElect = true for _, noDeploy := range app.StringSlice("no-deploy") { + if noDeploy == "servicelb" { + serverConfig.DisableServiceLB = true + continue + } + if !strings.HasSuffix(noDeploy, ".yaml") { noDeploy = noDeploy + ".yaml" } diff --git a/pkg/server/server.go b/pkg/server/server.go index 445aef1d5b..6c562223ab 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -17,7 +17,10 @@ import ( "github.com/rancher/k3s/pkg/daemons/config" "github.com/rancher/k3s/pkg/daemons/control" "github.com/rancher/k3s/pkg/deploy" + "github.com/rancher/k3s/pkg/servicelb" "github.com/rancher/k3s/pkg/tls" + appsv1 "github.com/rancher/k3s/types/apis/apps/v1" + corev1 "github.com/rancher/k3s/types/apis/core/v1" v1 "github.com/rancher/k3s/types/apis/k3s.cattle.io/v1" "github.com/rancher/norman" "github.com/rancher/norman/pkg/clientaccess" @@ -50,7 +53,7 @@ func StartServer(ctx context.Context, config *Config) (string, error) { return "", errors.Wrap(err, "starting kubernetes") } - certs, err := startNorman(ctx, &config.TLSConfig, &config.ControlConfig) + certs, err := startNorman(ctx, config) if err != nil { return "", errors.Wrap(err, "starting tls server") } @@ -66,13 +69,15 @@ func StartServer(ctx context.Context, config *Config) (string, error) { return certs, nil } -func startNorman(ctx context.Context, tlsConfig *dynamiclistener.UserConfig, config *config.Control) (string, error) { +func startNorman(ctx context.Context, config *Config) (string, error) { var ( - err error - tlsServer dynamiclistener.ServerInterface + err error + tlsServer dynamiclistener.ServerInterface + tlsConfig = &config.TLSConfig + controlConfig = &config.ControlConfig ) - tlsConfig.Handler = router(config, config.Runtime.Tunnel, func() (string, error) { + tlsConfig.Handler = router(controlConfig, controlConfig.Runtime.Tunnel, func() (string, error) { if tlsServer == nil { return "", nil } @@ -81,9 +86,11 @@ func startNorman(ctx context.Context, tlsConfig *dynamiclistener.UserConfig, con normanConfig := &norman.Config{ Name: "k3s", - KubeConfig: config.Runtime.KubeConfigSystem, + KubeConfig: controlConfig.Runtime.KubeConfigSystem, Clients: []norman.ClientFactory{ v1.Factory, + appsv1.Factory, + corev1.Factory, }, Schemas: []*types.Schemas{ v1.Schemas, @@ -102,11 +109,14 @@ func startNorman(ctx context.Context, tlsConfig *dynamiclistener.UserConfig, con DisableLeaderElection: true, MasterControllers: []norman.ControllerRegister{ func(ctx context.Context) error { - dataDir := filepath.Join(config.DataDir, "manifests") + return servicelb.Register(ctx, norman.GetServer(ctx).K8sClient, !config.DisableServiceLB) + }, + func(ctx context.Context) error { + dataDir := filepath.Join(controlConfig.DataDir, "manifests") if err := deploy.Stage(dataDir); err != nil { return err } - if err := deploy.WatchFiles(ctx, config.Skips, dataDir); err != nil { + if err := deploy.WatchFiles(ctx, controlConfig.Skips, dataDir); err != nil { return err } return nil diff --git a/pkg/server/types.go b/pkg/server/types.go index 63f0dc56d8..9dbcf44ad2 100644 --- a/pkg/server/types.go +++ b/pkg/server/types.go @@ -6,7 +6,8 @@ import ( ) type Config struct { - DisableAgent bool - TLSConfig dynamiclistener.UserConfig - ControlConfig config.Control + DisableAgent bool + DisableServiceLB bool + TLSConfig dynamiclistener.UserConfig + ControlConfig config.Control } diff --git a/pkg/servicelb/controller.go b/pkg/servicelb/controller.go new file mode 100644 index 0000000000..36ff1d1355 --- /dev/null +++ b/pkg/servicelb/controller.go @@ -0,0 +1,327 @@ +package servicelb + +import ( + "context" + "fmt" + "sort" + "strconv" + + appclient "github.com/rancher/k3s/types/apis/apps/v1" + coreclient "github.com/rancher/k3s/types/apis/core/v1" + "github.com/rancher/norman/condition" + "github.com/rancher/norman/pkg/changeset" + "github.com/rancher/norman/pkg/objectset" + "github.com/rancher/norman/types/slice" + "github.com/sirupsen/logrus" + apps "k8s.io/api/apps/v1" + core "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/client-go/kubernetes" + coregetter "k8s.io/client-go/kubernetes/typed/core/v1" +) + +const ( + image = "rancher/klipper-lb:v0.1.1" + svcNameLabel = "svccontroller.k3s.cattle.io/svcname" + Ready = condition.Cond("Ready") +) + +var ( + trueVal = true +) + +func Register(ctx context.Context, kubernetes kubernetes.Interface, enabled bool) error { + clients := coreclient.ClientsFrom(ctx) + appClients := appclient.ClientsFrom(ctx) + + h := &handler{ + enabled: enabled, + nodeCache: clients.Node.Cache(), + podCache: clients.Pod.Cache(), + processor: objectset.NewProcessor("svccontroller"). + Client(appClients.Deployment), + serviceCache: clients.Service.Cache(), + services: kubernetes.CoreV1(), + } + + clients.Service.OnChange(ctx, "svccontroller", h.onChange) + changeset.Watch(ctx, "svccontroller-watcher", + h.onPodChange, + clients.Service, + clients.Pod) + + return nil +} + +type handler struct { + enabled bool + nodeCache coreclient.NodeClientCache + podCache coreclient.PodClientCache + processor *objectset.Processor + serviceCache coreclient.ServiceClientCache + services coregetter.ServicesGetter +} + +func (h *handler) onPodChange(name, namespace string, obj runtime.Object) ([]changeset.Key, error) { + pod, ok := obj.(*core.Pod) + if !ok { + return nil, nil + } + + serviceName := pod.Labels[svcNameLabel] + if serviceName == "" { + return nil, nil + } + + if pod.Status.PodIP == "" { + return nil, nil + } + + return []changeset.Key{ + { + Name: serviceName, + Namespace: pod.Namespace, + }, + }, nil +} + +func (h *handler) onChange(svc *core.Service) (runtime.Object, error) { + if svc.Spec.Type != core.ServiceTypeLoadBalancer || svc.Spec.ClusterIP == "" || + svc.Spec.ClusterIP == "None" { + return svc, nil + } + + if err := h.deployPod(svc); err != nil { + return svc, err + } + + return h.updateService(svc) +} + +func (h *handler) updateService(svc *core.Service) (runtime.Object, error) { + pods, err := h.podCache.List(svc.Namespace, labels.SelectorFromSet(map[string]string{ + svcNameLabel: svc.Name, + })) + + if err != nil { + return svc, err + } + + existingIPs := serviceIPs(svc) + expectedIPs, err := h.podIPs(pods) + if err != nil { + return svc, err + } + + sort.Strings(expectedIPs) + sort.Strings(existingIPs) + + if slice.StringsEqual(expectedIPs, existingIPs) { + return svc, nil + } + + svc = svc.DeepCopy() + svc.Status.LoadBalancer.Ingress = nil + for _, ip := range expectedIPs { + svc.Status.LoadBalancer.Ingress = append(svc.Status.LoadBalancer.Ingress, core.LoadBalancerIngress{ + IP: ip, + }) + } + + logrus.Debugf("Setting service loadbalancer %s/%s to IPs %v", svc.Namespace, svc.Name, expectedIPs) + return h.services.Services(svc.Namespace).UpdateStatus(svc) +} + +func serviceIPs(svc *core.Service) []string { + var ips []string + + for _, ingress := range svc.Status.LoadBalancer.Ingress { + if ingress.IP != "" { + ips = append(ips, ingress.IP) + } + } + + return ips +} + +func (h *handler) podIPs(pods []*core.Pod) ([]string, error) { + ips := map[string]bool{} + + for _, pod := range pods { + if pod.Spec.NodeName == "" || pod.Status.PodIP == "" { + continue + } + if !Ready.IsTrue(pod) { + continue + } + + node, err := h.nodeCache.Get("", pod.Spec.NodeName) + if errors.IsNotFound(err) { + continue + } else if err != nil { + return nil, err + } + + for _, addr := range node.Status.Addresses { + if addr.Type == core.NodeInternalIP { + ips[addr.Address] = true + } + } + } + + var ipList []string + for k := range ips { + ipList = append(ipList, k) + } + return ipList, nil +} + +func (h *handler) deployPod(svc *core.Service) error { + objs := objectset.NewObjectSet() + if !h.enabled { + return h.processor.NewDesiredSet(svc, objs).Apply() + } + + dep, err := h.newDeployment(svc) + if err != nil { + return err + } + if dep != nil { + objs.Add(dep) + } + + return h.processor.NewDesiredSet(svc, objs).Apply() +} + +func (h *handler) resolvePort(svc *core.Service, targetPort core.ServicePort) (int32, error) { + if len(svc.Spec.Selector) == 0 { + return 0, nil + } + + if targetPort.TargetPort.IntVal != 0 { + return targetPort.TargetPort.IntVal, nil + } + + pods, err := h.podCache.List(svc.Namespace, labels.SelectorFromSet(svc.Spec.Selector)) + if err != nil { + return 0, err + } + + for _, pod := range pods { + if !Ready.IsTrue(pod) { + continue + } + for _, container := range pod.Spec.Containers { + for _, port := range container.Ports { + if port.Name == targetPort.TargetPort.StrVal { + return port.ContainerPort, nil + } + } + } + } + + return 0, nil +} + +func (h *handler) newDeployment(svc *core.Service) (*apps.Deployment, error) { + name := fmt.Sprintf("svclb-%s", svc.Name) + zero := intstr.FromInt(0) + one := intstr.FromInt(1) + two := int32(2) + + dep := &apps.Deployment{ + ObjectMeta: meta.ObjectMeta{ + Name: name, + Namespace: svc.Namespace, + OwnerReferences: []meta.OwnerReference{ + { + Name: svc.Name, + APIVersion: "v1", + Kind: "Service", + UID: svc.UID, + Controller: &trueVal, + }, + }, + }, + TypeMeta: meta.TypeMeta{ + Kind: "Deployment", + APIVersion: "apps/v1", + }, + Spec: apps.DeploymentSpec{ + Replicas: &two, + Selector: &meta.LabelSelector{ + MatchLabels: map[string]string{ + "app": name, + }, + }, + Template: core.PodTemplateSpec{ + ObjectMeta: meta.ObjectMeta{ + Labels: map[string]string{ + "app": name, + svcNameLabel: svc.Name, + }, + }, + }, + Strategy: apps.DeploymentStrategy{ + Type: apps.RollingUpdateDeploymentStrategyType, + RollingUpdate: &apps.RollingUpdateDeployment{ + MaxSurge: &zero, + MaxUnavailable: &one, + }, + }, + }, + } + + for _, port := range svc.Spec.Ports { + targetPort, err := h.resolvePort(svc, port) + if err != nil { + return nil, err + } + + container := core.Container{ + Name: fmt.Sprintf("port-%s", port.Name), + Image: image, + ImagePullPolicy: core.PullIfNotPresent, + Ports: []core.ContainerPort{ + { + Name: port.Name, + ContainerPort: port.Port, + HostPort: port.Port, + }, + }, + Env: []core.EnvVar{ + { + Name: "SRC_PORT", + Value: strconv.Itoa(int(port.Port)), + }, + { + Name: "DEST_PROTO", + Value: string(port.Protocol), + }, + { + Name: "DEST_PORT", + Value: strconv.Itoa(int(targetPort)), + }, + { + Name: "DEST_IP", + Value: svc.Spec.ClusterIP, + }, + }, + SecurityContext: &core.SecurityContext{ + Capabilities: &core.Capabilities{ + Add: []core.Capability{ + "NET_ADMIN", + }, + }, + }, + } + + dep.Spec.Template.Spec.Containers = append(dep.Spec.Template.Spec.Containers, container) + } + + return dep, nil +} diff --git a/scripts/dev-server.sh b/scripts/dev-server.sh index 255922f72b..98f8ebbcb6 100755 --- a/scripts/dev-server.sh +++ b/scripts/dev-server.sh @@ -5,4 +5,4 @@ mkdir -p $(dirname $0)/../bin cd $(dirname $0)/../bin echo Running -go run -tags "apparmor" ../main.go --debug server --disable-agent +go run -tags "apparmor" ../main.go --debug server --disable-agent "$@" diff --git a/types/apis/apps/v1/zz_generated_deepcopy.go b/types/apis/apps/v1/zz_generated_deepcopy.go new file mode 100644 index 0000000000..21217b15c4 --- /dev/null +++ b/types/apis/apps/v1/zz_generated_deepcopy.go @@ -0,0 +1,39 @@ +package v1 + +import ( + appsv1 "k8s.io/api/apps/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeploymentList) DeepCopyInto(out *DeploymentList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]appsv1.Deployment, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentList. +func (in *DeploymentList) DeepCopy() *DeploymentList { + if in == nil { + return nil + } + out := new(DeploymentList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DeploymentList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/types/apis/apps/v1/zz_generated_deployment_controller.go b/types/apis/apps/v1/zz_generated_deployment_controller.go new file mode 100644 index 0000000000..3ddb52c204 --- /dev/null +++ b/types/apis/apps/v1/zz_generated_deployment_controller.go @@ -0,0 +1,441 @@ +package v1 + +import ( + "context" + + "github.com/rancher/norman/controller" + "github.com/rancher/norman/objectclient" + v1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/tools/cache" +) + +var ( + DeploymentGroupVersionKind = schema.GroupVersionKind{ + Version: Version, + Group: GroupName, + Kind: "Deployment", + } + DeploymentResource = metav1.APIResource{ + Name: "deployments", + SingularName: "deployment", + Namespaced: true, + + Kind: DeploymentGroupVersionKind.Kind, + } +) + +func NewDeployment(namespace, name string, obj v1.Deployment) *v1.Deployment { + obj.APIVersion, obj.Kind = DeploymentGroupVersionKind.ToAPIVersionAndKind() + obj.Name = name + obj.Namespace = namespace + return &obj +} + +type DeploymentList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []v1.Deployment +} + +type DeploymentHandlerFunc func(key string, obj *v1.Deployment) (runtime.Object, error) + +type DeploymentChangeHandlerFunc func(obj *v1.Deployment) (runtime.Object, error) + +type DeploymentLister interface { + List(namespace string, selector labels.Selector) (ret []*v1.Deployment, err error) + Get(namespace, name string) (*v1.Deployment, error) +} + +type DeploymentController interface { + Generic() controller.GenericController + Informer() cache.SharedIndexInformer + Lister() DeploymentLister + AddHandler(ctx context.Context, name string, handler DeploymentHandlerFunc) + AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler DeploymentHandlerFunc) + Enqueue(namespace, name string) + Sync(ctx context.Context) error + Start(ctx context.Context, threadiness int) error +} + +type DeploymentInterface interface { + ObjectClient() *objectclient.ObjectClient + Create(*v1.Deployment) (*v1.Deployment, error) + GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Deployment, error) + Get(name string, opts metav1.GetOptions) (*v1.Deployment, error) + Update(*v1.Deployment) (*v1.Deployment, error) + Delete(name string, options *metav1.DeleteOptions) error + DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error + List(opts metav1.ListOptions) (*DeploymentList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error + Controller() DeploymentController + AddHandler(ctx context.Context, name string, sync DeploymentHandlerFunc) + AddLifecycle(ctx context.Context, name string, lifecycle DeploymentLifecycle) + AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync DeploymentHandlerFunc) + AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle DeploymentLifecycle) +} + +type deploymentLister struct { + controller *deploymentController +} + +func (l *deploymentLister) List(namespace string, selector labels.Selector) (ret []*v1.Deployment, err error) { + err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { + ret = append(ret, obj.(*v1.Deployment)) + }) + return +} + +func (l *deploymentLister) Get(namespace, name string) (*v1.Deployment, error) { + var key string + if namespace != "" { + key = namespace + "/" + name + } else { + key = name + } + obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(schema.GroupResource{ + Group: DeploymentGroupVersionKind.Group, + Resource: "deployment", + }, key) + } + return obj.(*v1.Deployment), nil +} + +type deploymentController struct { + controller.GenericController +} + +func (c *deploymentController) Generic() controller.GenericController { + return c.GenericController +} + +func (c *deploymentController) Lister() DeploymentLister { + return &deploymentLister{ + controller: c, + } +} + +func (c *deploymentController) AddHandler(ctx context.Context, name string, handler DeploymentHandlerFunc) { + c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { + if obj == nil { + return handler(key, nil) + } else if v, ok := obj.(*v1.Deployment); ok { + return handler(key, v) + } else { + return nil, nil + } + }) +} + +func (c *deploymentController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler DeploymentHandlerFunc) { + c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { + if obj == nil { + return handler(key, nil) + } else if v, ok := obj.(*v1.Deployment); ok && controller.ObjectInCluster(cluster, obj) { + return handler(key, v) + } else { + return nil, nil + } + }) +} + +type deploymentFactory struct { +} + +func (c deploymentFactory) Object() runtime.Object { + return &v1.Deployment{} +} + +func (c deploymentFactory) List() runtime.Object { + return &DeploymentList{} +} + +func (s *deploymentClient) Controller() DeploymentController { + s.client.Lock() + defer s.client.Unlock() + + c, ok := s.client.deploymentControllers[s.ns] + if ok { + return c + } + + genericController := controller.NewGenericController(DeploymentGroupVersionKind.Kind+"Controller", + s.objectClient) + + c = &deploymentController{ + GenericController: genericController, + } + + s.client.deploymentControllers[s.ns] = c + s.client.starters = append(s.client.starters, c) + + return c +} + +type deploymentClient struct { + client *Client + ns string + objectClient *objectclient.ObjectClient + controller DeploymentController +} + +func (s *deploymentClient) ObjectClient() *objectclient.ObjectClient { + return s.objectClient +} + +func (s *deploymentClient) Create(o *v1.Deployment) (*v1.Deployment, error) { + obj, err := s.objectClient.Create(o) + return obj.(*v1.Deployment), err +} + +func (s *deploymentClient) Get(name string, opts metav1.GetOptions) (*v1.Deployment, error) { + obj, err := s.objectClient.Get(name, opts) + return obj.(*v1.Deployment), err +} + +func (s *deploymentClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Deployment, error) { + obj, err := s.objectClient.GetNamespaced(namespace, name, opts) + return obj.(*v1.Deployment), err +} + +func (s *deploymentClient) Update(o *v1.Deployment) (*v1.Deployment, error) { + obj, err := s.objectClient.Update(o.Name, o) + return obj.(*v1.Deployment), err +} + +func (s *deploymentClient) Delete(name string, options *metav1.DeleteOptions) error { + return s.objectClient.Delete(name, options) +} + +func (s *deploymentClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { + return s.objectClient.DeleteNamespaced(namespace, name, options) +} + +func (s *deploymentClient) List(opts metav1.ListOptions) (*DeploymentList, error) { + obj, err := s.objectClient.List(opts) + return obj.(*DeploymentList), err +} + +func (s *deploymentClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { + return s.objectClient.Watch(opts) +} + +// Patch applies the patch and returns the patched deployment. +func (s *deploymentClient) Patch(o *v1.Deployment, patchType types.PatchType, data []byte, subresources ...string) (*v1.Deployment, error) { + obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) + return obj.(*v1.Deployment), err +} + +func (s *deploymentClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { + return s.objectClient.DeleteCollection(deleteOpts, listOpts) +} + +func (s *deploymentClient) AddHandler(ctx context.Context, name string, sync DeploymentHandlerFunc) { + s.Controller().AddHandler(ctx, name, sync) +} + +func (s *deploymentClient) AddLifecycle(ctx context.Context, name string, lifecycle DeploymentLifecycle) { + sync := NewDeploymentLifecycleAdapter(name, false, s, lifecycle) + s.Controller().AddHandler(ctx, name, sync) +} + +func (s *deploymentClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync DeploymentHandlerFunc) { + s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) +} + +func (s *deploymentClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle DeploymentLifecycle) { + sync := NewDeploymentLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) + s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) +} + +type DeploymentIndexer func(obj *v1.Deployment) ([]string, error) + +type DeploymentClientCache interface { + Get(namespace, name string) (*v1.Deployment, error) + List(namespace string, selector labels.Selector) ([]*v1.Deployment, error) + + Index(name string, indexer DeploymentIndexer) + GetIndexed(name, key string) ([]*v1.Deployment, error) +} + +type DeploymentClient interface { + Create(*v1.Deployment) (*v1.Deployment, error) + Get(namespace, name string, opts metav1.GetOptions) (*v1.Deployment, error) + Update(*v1.Deployment) (*v1.Deployment, error) + Delete(namespace, name string, options *metav1.DeleteOptions) error + List(namespace string, opts metav1.ListOptions) (*DeploymentList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + + Cache() DeploymentClientCache + + OnCreate(ctx context.Context, name string, sync DeploymentChangeHandlerFunc) + OnChange(ctx context.Context, name string, sync DeploymentChangeHandlerFunc) + OnRemove(ctx context.Context, name string, sync DeploymentChangeHandlerFunc) + Enqueue(namespace, name string) + + Generic() controller.GenericController + ObjectClient() *objectclient.ObjectClient + Interface() DeploymentInterface +} + +type deploymentClientCache struct { + client *deploymentClient2 +} + +type deploymentClient2 struct { + iface DeploymentInterface + controller DeploymentController +} + +func (n *deploymentClient2) Interface() DeploymentInterface { + return n.iface +} + +func (n *deploymentClient2) Generic() controller.GenericController { + return n.iface.Controller().Generic() +} + +func (n *deploymentClient2) ObjectClient() *objectclient.ObjectClient { + return n.Interface().ObjectClient() +} + +func (n *deploymentClient2) Enqueue(namespace, name string) { + n.iface.Controller().Enqueue(namespace, name) +} + +func (n *deploymentClient2) Create(obj *v1.Deployment) (*v1.Deployment, error) { + return n.iface.Create(obj) +} + +func (n *deploymentClient2) Get(namespace, name string, opts metav1.GetOptions) (*v1.Deployment, error) { + return n.iface.GetNamespaced(namespace, name, opts) +} + +func (n *deploymentClient2) Update(obj *v1.Deployment) (*v1.Deployment, error) { + return n.iface.Update(obj) +} + +func (n *deploymentClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return n.iface.DeleteNamespaced(namespace, name, options) +} + +func (n *deploymentClient2) List(namespace string, opts metav1.ListOptions) (*DeploymentList, error) { + return n.iface.List(opts) +} + +func (n *deploymentClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { + return n.iface.Watch(opts) +} + +func (n *deploymentClientCache) Get(namespace, name string) (*v1.Deployment, error) { + return n.client.controller.Lister().Get(namespace, name) +} + +func (n *deploymentClientCache) List(namespace string, selector labels.Selector) ([]*v1.Deployment, error) { + return n.client.controller.Lister().List(namespace, selector) +} + +func (n *deploymentClient2) Cache() DeploymentClientCache { + n.loadController() + return &deploymentClientCache{ + client: n, + } +} + +func (n *deploymentClient2) OnCreate(ctx context.Context, name string, sync DeploymentChangeHandlerFunc) { + n.loadController() + n.iface.AddLifecycle(ctx, name+"-create", &deploymentLifecycleDelegate{create: sync}) +} + +func (n *deploymentClient2) OnChange(ctx context.Context, name string, sync DeploymentChangeHandlerFunc) { + n.loadController() + n.iface.AddLifecycle(ctx, name+"-change", &deploymentLifecycleDelegate{update: sync}) +} + +func (n *deploymentClient2) OnRemove(ctx context.Context, name string, sync DeploymentChangeHandlerFunc) { + n.loadController() + n.iface.AddLifecycle(ctx, name, &deploymentLifecycleDelegate{remove: sync}) +} + +func (n *deploymentClientCache) Index(name string, indexer DeploymentIndexer) { + err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ + name: func(obj interface{}) ([]string, error) { + if v, ok := obj.(*v1.Deployment); ok { + return indexer(v) + } + return nil, nil + }, + }) + + if err != nil { + panic(err) + } +} + +func (n *deploymentClientCache) GetIndexed(name, key string) ([]*v1.Deployment, error) { + var result []*v1.Deployment + objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + if v, ok := obj.(*v1.Deployment); ok { + result = append(result, v) + } + } + + return result, nil +} + +func (n *deploymentClient2) loadController() { + if n.controller == nil { + n.controller = n.iface.Controller() + } +} + +type deploymentLifecycleDelegate struct { + create DeploymentChangeHandlerFunc + update DeploymentChangeHandlerFunc + remove DeploymentChangeHandlerFunc +} + +func (n *deploymentLifecycleDelegate) HasCreate() bool { + return n.create != nil +} + +func (n *deploymentLifecycleDelegate) Create(obj *v1.Deployment) (runtime.Object, error) { + if n.create == nil { + return obj, nil + } + return n.create(obj) +} + +func (n *deploymentLifecycleDelegate) HasFinalize() bool { + return n.remove != nil +} + +func (n *deploymentLifecycleDelegate) Remove(obj *v1.Deployment) (runtime.Object, error) { + if n.remove == nil { + return obj, nil + } + return n.remove(obj) +} + +func (n *deploymentLifecycleDelegate) Updated(obj *v1.Deployment) (runtime.Object, error) { + if n.update == nil { + return obj, nil + } + return n.update(obj) +} diff --git a/types/apis/apps/v1/zz_generated_deployment_lifecycle_adapter.go b/types/apis/apps/v1/zz_generated_deployment_lifecycle_adapter.go new file mode 100644 index 0000000000..152b5058b7 --- /dev/null +++ b/types/apis/apps/v1/zz_generated_deployment_lifecycle_adapter.go @@ -0,0 +1,63 @@ +package v1 + +import ( + "github.com/rancher/norman/lifecycle" + v1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +type DeploymentLifecycle interface { + Create(obj *v1.Deployment) (runtime.Object, error) + Remove(obj *v1.Deployment) (runtime.Object, error) + Updated(obj *v1.Deployment) (runtime.Object, error) +} + +type deploymentLifecycleAdapter struct { + lifecycle DeploymentLifecycle +} + +func (w *deploymentLifecycleAdapter) HasCreate() bool { + o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) + return !ok || o.HasCreate() +} + +func (w *deploymentLifecycleAdapter) HasFinalize() bool { + o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) + return !ok || o.HasFinalize() +} + +func (w *deploymentLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { + o, err := w.lifecycle.Create(obj.(*v1.Deployment)) + if o == nil { + return nil, err + } + return o, err +} + +func (w *deploymentLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { + o, err := w.lifecycle.Remove(obj.(*v1.Deployment)) + if o == nil { + return nil, err + } + return o, err +} + +func (w *deploymentLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { + o, err := w.lifecycle.Updated(obj.(*v1.Deployment)) + if o == nil { + return nil, err + } + return o, err +} + +func NewDeploymentLifecycleAdapter(name string, clusterScoped bool, client DeploymentInterface, l DeploymentLifecycle) DeploymentHandlerFunc { + adapter := &deploymentLifecycleAdapter{lifecycle: l} + syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) + return func(key string, obj *v1.Deployment) (runtime.Object, error) { + newObj, err := syncFn(key, obj) + if o, ok := newObj.(runtime.Object); ok { + return o, err + } + return nil, err + } +} diff --git a/types/apis/apps/v1/zz_generated_k8s_client.go b/types/apis/apps/v1/zz_generated_k8s_client.go new file mode 100644 index 0000000000..93ebcc6b8c --- /dev/null +++ b/types/apis/apps/v1/zz_generated_k8s_client.go @@ -0,0 +1,119 @@ +package v1 + +import ( + "context" + "sync" + + "github.com/rancher/norman/controller" + "github.com/rancher/norman/objectclient" + "github.com/rancher/norman/objectclient/dynamic" + "github.com/rancher/norman/restwatch" + "k8s.io/client-go/rest" +) + +type ( + contextKeyType struct{} + contextClientsKeyType struct{} +) + +type Interface interface { + RESTClient() rest.Interface + controller.Starter + + DeploymentsGetter +} + +type Clients struct { + Interface Interface + + Deployment DeploymentClient +} + +type Client struct { + sync.Mutex + restClient rest.Interface + starters []controller.Starter + + deploymentControllers map[string]DeploymentController +} + +func Factory(ctx context.Context, config rest.Config) (context.Context, controller.Starter, error) { + c, err := NewForConfig(config) + if err != nil { + return ctx, nil, err + } + + cs := NewClientsFromInterface(c) + + ctx = context.WithValue(ctx, contextKeyType{}, c) + ctx = context.WithValue(ctx, contextClientsKeyType{}, cs) + return ctx, c, nil +} + +func ClientsFrom(ctx context.Context) *Clients { + return ctx.Value(contextClientsKeyType{}).(*Clients) +} + +func From(ctx context.Context) Interface { + return ctx.Value(contextKeyType{}).(Interface) +} + +func NewClients(config rest.Config) (*Clients, error) { + iface, err := NewForConfig(config) + if err != nil { + return nil, err + } + return NewClientsFromInterface(iface), nil +} + +func NewClientsFromInterface(iface Interface) *Clients { + return &Clients{ + Interface: iface, + + Deployment: &deploymentClient2{ + iface: iface.Deployments(""), + }, + } +} + +func NewForConfig(config rest.Config) (Interface, error) { + if config.NegotiatedSerializer == nil { + config.NegotiatedSerializer = dynamic.NegotiatedSerializer + } + + restClient, err := restwatch.UnversionedRESTClientFor(&config) + if err != nil { + return nil, err + } + + return &Client{ + restClient: restClient, + + deploymentControllers: map[string]DeploymentController{}, + }, nil +} + +func (c *Client) RESTClient() rest.Interface { + return c.restClient +} + +func (c *Client) Sync(ctx context.Context) error { + return controller.Sync(ctx, c.starters...) +} + +func (c *Client) Start(ctx context.Context, threadiness int) error { + return controller.Start(ctx, threadiness, c.starters...) +} + +type DeploymentsGetter interface { + Deployments(namespace string) DeploymentInterface +} + +func (c *Client) Deployments(namespace string) DeploymentInterface { + objectClient := objectclient.NewObjectClient(namespace, c.restClient, &DeploymentResource, DeploymentGroupVersionKind, deploymentFactory{}) + return &deploymentClient{ + ns: namespace, + client: c, + objectClient: objectClient, + } +} diff --git a/types/apis/apps/v1/zz_generated_scheme.go b/types/apis/apps/v1/zz_generated_scheme.go new file mode 100644 index 0000000000..3e89617f30 --- /dev/null +++ b/types/apis/apps/v1/zz_generated_scheme.go @@ -0,0 +1,39 @@ +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +const ( + GroupName = "apps" + Version = "v1" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: Version} + +// Kind takes an unqualified kind and returns a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + // TODO this gets cleaned up when the types are fixed + scheme.AddKnownTypes(SchemeGroupVersion, + + &DeploymentList{}, + ) + return nil +} diff --git a/types/apis/core/v1/zz_generated_deepcopy.go b/types/apis/core/v1/zz_generated_deepcopy.go new file mode 100644 index 0000000000..c4c15f2d36 --- /dev/null +++ b/types/apis/core/v1/zz_generated_deepcopy.go @@ -0,0 +1,105 @@ +package v1 + +import ( + corev1 "k8s.io/api/core/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeList) DeepCopyInto(out *NodeList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]corev1.Node, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeList. +func (in *NodeList) DeepCopy() *NodeList { + if in == nil { + return nil + } + out := new(NodeList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodList) DeepCopyInto(out *PodList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]corev1.Pod, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodList. +func (in *PodList) DeepCopy() *PodList { + if in == nil { + return nil + } + out := new(PodList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PodList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceList) DeepCopyInto(out *ServiceList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]corev1.Service, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceList. +func (in *ServiceList) DeepCopy() *ServiceList { + if in == nil { + return nil + } + out := new(ServiceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/types/apis/core/v1/zz_generated_k8s_client.go b/types/apis/core/v1/zz_generated_k8s_client.go new file mode 100644 index 0000000000..f046428154 --- /dev/null +++ b/types/apis/core/v1/zz_generated_k8s_client.go @@ -0,0 +1,159 @@ +package v1 + +import ( + "context" + "sync" + + "github.com/rancher/norman/controller" + "github.com/rancher/norman/objectclient" + "github.com/rancher/norman/objectclient/dynamic" + "github.com/rancher/norman/restwatch" + "k8s.io/client-go/rest" +) + +type ( + contextKeyType struct{} + contextClientsKeyType struct{} +) + +type Interface interface { + RESTClient() rest.Interface + controller.Starter + + NodesGetter + ServicesGetter + PodsGetter +} + +type Clients struct { + Interface Interface + + Node NodeClient + Service ServiceClient + Pod PodClient +} + +type Client struct { + sync.Mutex + restClient rest.Interface + starters []controller.Starter + + nodeControllers map[string]NodeController + serviceControllers map[string]ServiceController + podControllers map[string]PodController +} + +func Factory(ctx context.Context, config rest.Config) (context.Context, controller.Starter, error) { + c, err := NewForConfig(config) + if err != nil { + return ctx, nil, err + } + + cs := NewClientsFromInterface(c) + + ctx = context.WithValue(ctx, contextKeyType{}, c) + ctx = context.WithValue(ctx, contextClientsKeyType{}, cs) + return ctx, c, nil +} + +func ClientsFrom(ctx context.Context) *Clients { + return ctx.Value(contextClientsKeyType{}).(*Clients) +} + +func From(ctx context.Context) Interface { + return ctx.Value(contextKeyType{}).(Interface) +} + +func NewClients(config rest.Config) (*Clients, error) { + iface, err := NewForConfig(config) + if err != nil { + return nil, err + } + return NewClientsFromInterface(iface), nil +} + +func NewClientsFromInterface(iface Interface) *Clients { + return &Clients{ + Interface: iface, + + Node: &nodeClient2{ + iface: iface.Nodes(""), + }, + Service: &serviceClient2{ + iface: iface.Services(""), + }, + Pod: &podClient2{ + iface: iface.Pods(""), + }, + } +} + +func NewForConfig(config rest.Config) (Interface, error) { + if config.NegotiatedSerializer == nil { + config.NegotiatedSerializer = dynamic.NegotiatedSerializer + } + + restClient, err := restwatch.UnversionedRESTClientFor(&config) + if err != nil { + return nil, err + } + + return &Client{ + restClient: restClient, + + nodeControllers: map[string]NodeController{}, + serviceControllers: map[string]ServiceController{}, + podControllers: map[string]PodController{}, + }, nil +} + +func (c *Client) RESTClient() rest.Interface { + return c.restClient +} + +func (c *Client) Sync(ctx context.Context) error { + return controller.Sync(ctx, c.starters...) +} + +func (c *Client) Start(ctx context.Context, threadiness int) error { + return controller.Start(ctx, threadiness, c.starters...) +} + +type NodesGetter interface { + Nodes(namespace string) NodeInterface +} + +func (c *Client) Nodes(namespace string) NodeInterface { + objectClient := objectclient.NewObjectClient(namespace, c.restClient, &NodeResource, NodeGroupVersionKind, nodeFactory{}) + return &nodeClient{ + ns: namespace, + client: c, + objectClient: objectClient, + } +} + +type ServicesGetter interface { + Services(namespace string) ServiceInterface +} + +func (c *Client) Services(namespace string) ServiceInterface { + objectClient := objectclient.NewObjectClient(namespace, c.restClient, &ServiceResource, ServiceGroupVersionKind, serviceFactory{}) + return &serviceClient{ + ns: namespace, + client: c, + objectClient: objectClient, + } +} + +type PodsGetter interface { + Pods(namespace string) PodInterface +} + +func (c *Client) Pods(namespace string) PodInterface { + objectClient := objectclient.NewObjectClient(namespace, c.restClient, &PodResource, PodGroupVersionKind, podFactory{}) + return &podClient{ + ns: namespace, + client: c, + objectClient: objectClient, + } +} diff --git a/types/apis/core/v1/zz_generated_node_controller.go b/types/apis/core/v1/zz_generated_node_controller.go new file mode 100644 index 0000000000..031977f018 --- /dev/null +++ b/types/apis/core/v1/zz_generated_node_controller.go @@ -0,0 +1,440 @@ +package v1 + +import ( + "context" + + "github.com/rancher/norman/controller" + "github.com/rancher/norman/objectclient" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/tools/cache" +) + +var ( + NodeGroupVersionKind = schema.GroupVersionKind{ + Version: Version, + Group: GroupName, + Kind: "Node", + } + NodeResource = metav1.APIResource{ + Name: "nodes", + SingularName: "node", + Namespaced: false, + Kind: NodeGroupVersionKind.Kind, + } +) + +func NewNode(namespace, name string, obj v1.Node) *v1.Node { + obj.APIVersion, obj.Kind = NodeGroupVersionKind.ToAPIVersionAndKind() + obj.Name = name + obj.Namespace = namespace + return &obj +} + +type NodeList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []v1.Node +} + +type NodeHandlerFunc func(key string, obj *v1.Node) (runtime.Object, error) + +type NodeChangeHandlerFunc func(obj *v1.Node) (runtime.Object, error) + +type NodeLister interface { + List(namespace string, selector labels.Selector) (ret []*v1.Node, err error) + Get(namespace, name string) (*v1.Node, error) +} + +type NodeController interface { + Generic() controller.GenericController + Informer() cache.SharedIndexInformer + Lister() NodeLister + AddHandler(ctx context.Context, name string, handler NodeHandlerFunc) + AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler NodeHandlerFunc) + Enqueue(namespace, name string) + Sync(ctx context.Context) error + Start(ctx context.Context, threadiness int) error +} + +type NodeInterface interface { + ObjectClient() *objectclient.ObjectClient + Create(*v1.Node) (*v1.Node, error) + GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Node, error) + Get(name string, opts metav1.GetOptions) (*v1.Node, error) + Update(*v1.Node) (*v1.Node, error) + Delete(name string, options *metav1.DeleteOptions) error + DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error + List(opts metav1.ListOptions) (*NodeList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error + Controller() NodeController + AddHandler(ctx context.Context, name string, sync NodeHandlerFunc) + AddLifecycle(ctx context.Context, name string, lifecycle NodeLifecycle) + AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync NodeHandlerFunc) + AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle NodeLifecycle) +} + +type nodeLister struct { + controller *nodeController +} + +func (l *nodeLister) List(namespace string, selector labels.Selector) (ret []*v1.Node, err error) { + err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { + ret = append(ret, obj.(*v1.Node)) + }) + return +} + +func (l *nodeLister) Get(namespace, name string) (*v1.Node, error) { + var key string + if namespace != "" { + key = namespace + "/" + name + } else { + key = name + } + obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(schema.GroupResource{ + Group: NodeGroupVersionKind.Group, + Resource: "node", + }, key) + } + return obj.(*v1.Node), nil +} + +type nodeController struct { + controller.GenericController +} + +func (c *nodeController) Generic() controller.GenericController { + return c.GenericController +} + +func (c *nodeController) Lister() NodeLister { + return &nodeLister{ + controller: c, + } +} + +func (c *nodeController) AddHandler(ctx context.Context, name string, handler NodeHandlerFunc) { + c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { + if obj == nil { + return handler(key, nil) + } else if v, ok := obj.(*v1.Node); ok { + return handler(key, v) + } else { + return nil, nil + } + }) +} + +func (c *nodeController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler NodeHandlerFunc) { + c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { + if obj == nil { + return handler(key, nil) + } else if v, ok := obj.(*v1.Node); ok && controller.ObjectInCluster(cluster, obj) { + return handler(key, v) + } else { + return nil, nil + } + }) +} + +type nodeFactory struct { +} + +func (c nodeFactory) Object() runtime.Object { + return &v1.Node{} +} + +func (c nodeFactory) List() runtime.Object { + return &NodeList{} +} + +func (s *nodeClient) Controller() NodeController { + s.client.Lock() + defer s.client.Unlock() + + c, ok := s.client.nodeControllers[s.ns] + if ok { + return c + } + + genericController := controller.NewGenericController(NodeGroupVersionKind.Kind+"Controller", + s.objectClient) + + c = &nodeController{ + GenericController: genericController, + } + + s.client.nodeControllers[s.ns] = c + s.client.starters = append(s.client.starters, c) + + return c +} + +type nodeClient struct { + client *Client + ns string + objectClient *objectclient.ObjectClient + controller NodeController +} + +func (s *nodeClient) ObjectClient() *objectclient.ObjectClient { + return s.objectClient +} + +func (s *nodeClient) Create(o *v1.Node) (*v1.Node, error) { + obj, err := s.objectClient.Create(o) + return obj.(*v1.Node), err +} + +func (s *nodeClient) Get(name string, opts metav1.GetOptions) (*v1.Node, error) { + obj, err := s.objectClient.Get(name, opts) + return obj.(*v1.Node), err +} + +func (s *nodeClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Node, error) { + obj, err := s.objectClient.GetNamespaced(namespace, name, opts) + return obj.(*v1.Node), err +} + +func (s *nodeClient) Update(o *v1.Node) (*v1.Node, error) { + obj, err := s.objectClient.Update(o.Name, o) + return obj.(*v1.Node), err +} + +func (s *nodeClient) Delete(name string, options *metav1.DeleteOptions) error { + return s.objectClient.Delete(name, options) +} + +func (s *nodeClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { + return s.objectClient.DeleteNamespaced(namespace, name, options) +} + +func (s *nodeClient) List(opts metav1.ListOptions) (*NodeList, error) { + obj, err := s.objectClient.List(opts) + return obj.(*NodeList), err +} + +func (s *nodeClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { + return s.objectClient.Watch(opts) +} + +// Patch applies the patch and returns the patched deployment. +func (s *nodeClient) Patch(o *v1.Node, patchType types.PatchType, data []byte, subresources ...string) (*v1.Node, error) { + obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) + return obj.(*v1.Node), err +} + +func (s *nodeClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { + return s.objectClient.DeleteCollection(deleteOpts, listOpts) +} + +func (s *nodeClient) AddHandler(ctx context.Context, name string, sync NodeHandlerFunc) { + s.Controller().AddHandler(ctx, name, sync) +} + +func (s *nodeClient) AddLifecycle(ctx context.Context, name string, lifecycle NodeLifecycle) { + sync := NewNodeLifecycleAdapter(name, false, s, lifecycle) + s.Controller().AddHandler(ctx, name, sync) +} + +func (s *nodeClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync NodeHandlerFunc) { + s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) +} + +func (s *nodeClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle NodeLifecycle) { + sync := NewNodeLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) + s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) +} + +type NodeIndexer func(obj *v1.Node) ([]string, error) + +type NodeClientCache interface { + Get(namespace, name string) (*v1.Node, error) + List(namespace string, selector labels.Selector) ([]*v1.Node, error) + + Index(name string, indexer NodeIndexer) + GetIndexed(name, key string) ([]*v1.Node, error) +} + +type NodeClient interface { + Create(*v1.Node) (*v1.Node, error) + Get(namespace, name string, opts metav1.GetOptions) (*v1.Node, error) + Update(*v1.Node) (*v1.Node, error) + Delete(namespace, name string, options *metav1.DeleteOptions) error + List(namespace string, opts metav1.ListOptions) (*NodeList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + + Cache() NodeClientCache + + OnCreate(ctx context.Context, name string, sync NodeChangeHandlerFunc) + OnChange(ctx context.Context, name string, sync NodeChangeHandlerFunc) + OnRemove(ctx context.Context, name string, sync NodeChangeHandlerFunc) + Enqueue(namespace, name string) + + Generic() controller.GenericController + ObjectClient() *objectclient.ObjectClient + Interface() NodeInterface +} + +type nodeClientCache struct { + client *nodeClient2 +} + +type nodeClient2 struct { + iface NodeInterface + controller NodeController +} + +func (n *nodeClient2) Interface() NodeInterface { + return n.iface +} + +func (n *nodeClient2) Generic() controller.GenericController { + return n.iface.Controller().Generic() +} + +func (n *nodeClient2) ObjectClient() *objectclient.ObjectClient { + return n.Interface().ObjectClient() +} + +func (n *nodeClient2) Enqueue(namespace, name string) { + n.iface.Controller().Enqueue(namespace, name) +} + +func (n *nodeClient2) Create(obj *v1.Node) (*v1.Node, error) { + return n.iface.Create(obj) +} + +func (n *nodeClient2) Get(namespace, name string, opts metav1.GetOptions) (*v1.Node, error) { + return n.iface.GetNamespaced(namespace, name, opts) +} + +func (n *nodeClient2) Update(obj *v1.Node) (*v1.Node, error) { + return n.iface.Update(obj) +} + +func (n *nodeClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return n.iface.DeleteNamespaced(namespace, name, options) +} + +func (n *nodeClient2) List(namespace string, opts metav1.ListOptions) (*NodeList, error) { + return n.iface.List(opts) +} + +func (n *nodeClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { + return n.iface.Watch(opts) +} + +func (n *nodeClientCache) Get(namespace, name string) (*v1.Node, error) { + return n.client.controller.Lister().Get(namespace, name) +} + +func (n *nodeClientCache) List(namespace string, selector labels.Selector) ([]*v1.Node, error) { + return n.client.controller.Lister().List(namespace, selector) +} + +func (n *nodeClient2) Cache() NodeClientCache { + n.loadController() + return &nodeClientCache{ + client: n, + } +} + +func (n *nodeClient2) OnCreate(ctx context.Context, name string, sync NodeChangeHandlerFunc) { + n.loadController() + n.iface.AddLifecycle(ctx, name+"-create", &nodeLifecycleDelegate{create: sync}) +} + +func (n *nodeClient2) OnChange(ctx context.Context, name string, sync NodeChangeHandlerFunc) { + n.loadController() + n.iface.AddLifecycle(ctx, name+"-change", &nodeLifecycleDelegate{update: sync}) +} + +func (n *nodeClient2) OnRemove(ctx context.Context, name string, sync NodeChangeHandlerFunc) { + n.loadController() + n.iface.AddLifecycle(ctx, name, &nodeLifecycleDelegate{remove: sync}) +} + +func (n *nodeClientCache) Index(name string, indexer NodeIndexer) { + err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ + name: func(obj interface{}) ([]string, error) { + if v, ok := obj.(*v1.Node); ok { + return indexer(v) + } + return nil, nil + }, + }) + + if err != nil { + panic(err) + } +} + +func (n *nodeClientCache) GetIndexed(name, key string) ([]*v1.Node, error) { + var result []*v1.Node + objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + if v, ok := obj.(*v1.Node); ok { + result = append(result, v) + } + } + + return result, nil +} + +func (n *nodeClient2) loadController() { + if n.controller == nil { + n.controller = n.iface.Controller() + } +} + +type nodeLifecycleDelegate struct { + create NodeChangeHandlerFunc + update NodeChangeHandlerFunc + remove NodeChangeHandlerFunc +} + +func (n *nodeLifecycleDelegate) HasCreate() bool { + return n.create != nil +} + +func (n *nodeLifecycleDelegate) Create(obj *v1.Node) (runtime.Object, error) { + if n.create == nil { + return obj, nil + } + return n.create(obj) +} + +func (n *nodeLifecycleDelegate) HasFinalize() bool { + return n.remove != nil +} + +func (n *nodeLifecycleDelegate) Remove(obj *v1.Node) (runtime.Object, error) { + if n.remove == nil { + return obj, nil + } + return n.remove(obj) +} + +func (n *nodeLifecycleDelegate) Updated(obj *v1.Node) (runtime.Object, error) { + if n.update == nil { + return obj, nil + } + return n.update(obj) +} diff --git a/types/apis/core/v1/zz_generated_node_lifecycle_adapter.go b/types/apis/core/v1/zz_generated_node_lifecycle_adapter.go new file mode 100644 index 0000000000..9cd3306a53 --- /dev/null +++ b/types/apis/core/v1/zz_generated_node_lifecycle_adapter.go @@ -0,0 +1,63 @@ +package v1 + +import ( + "github.com/rancher/norman/lifecycle" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +type NodeLifecycle interface { + Create(obj *v1.Node) (runtime.Object, error) + Remove(obj *v1.Node) (runtime.Object, error) + Updated(obj *v1.Node) (runtime.Object, error) +} + +type nodeLifecycleAdapter struct { + lifecycle NodeLifecycle +} + +func (w *nodeLifecycleAdapter) HasCreate() bool { + o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) + return !ok || o.HasCreate() +} + +func (w *nodeLifecycleAdapter) HasFinalize() bool { + o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) + return !ok || o.HasFinalize() +} + +func (w *nodeLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { + o, err := w.lifecycle.Create(obj.(*v1.Node)) + if o == nil { + return nil, err + } + return o, err +} + +func (w *nodeLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { + o, err := w.lifecycle.Remove(obj.(*v1.Node)) + if o == nil { + return nil, err + } + return o, err +} + +func (w *nodeLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { + o, err := w.lifecycle.Updated(obj.(*v1.Node)) + if o == nil { + return nil, err + } + return o, err +} + +func NewNodeLifecycleAdapter(name string, clusterScoped bool, client NodeInterface, l NodeLifecycle) NodeHandlerFunc { + adapter := &nodeLifecycleAdapter{lifecycle: l} + syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) + return func(key string, obj *v1.Node) (runtime.Object, error) { + newObj, err := syncFn(key, obj) + if o, ok := newObj.(runtime.Object); ok { + return o, err + } + return nil, err + } +} diff --git a/types/apis/core/v1/zz_generated_pod_controller.go b/types/apis/core/v1/zz_generated_pod_controller.go new file mode 100644 index 0000000000..421678df19 --- /dev/null +++ b/types/apis/core/v1/zz_generated_pod_controller.go @@ -0,0 +1,441 @@ +package v1 + +import ( + "context" + + "github.com/rancher/norman/controller" + "github.com/rancher/norman/objectclient" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/tools/cache" +) + +var ( + PodGroupVersionKind = schema.GroupVersionKind{ + Version: Version, + Group: GroupName, + Kind: "Pod", + } + PodResource = metav1.APIResource{ + Name: "pods", + SingularName: "pod", + Namespaced: true, + + Kind: PodGroupVersionKind.Kind, + } +) + +func NewPod(namespace, name string, obj v1.Pod) *v1.Pod { + obj.APIVersion, obj.Kind = PodGroupVersionKind.ToAPIVersionAndKind() + obj.Name = name + obj.Namespace = namespace + return &obj +} + +type PodList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []v1.Pod +} + +type PodHandlerFunc func(key string, obj *v1.Pod) (runtime.Object, error) + +type PodChangeHandlerFunc func(obj *v1.Pod) (runtime.Object, error) + +type PodLister interface { + List(namespace string, selector labels.Selector) (ret []*v1.Pod, err error) + Get(namespace, name string) (*v1.Pod, error) +} + +type PodController interface { + Generic() controller.GenericController + Informer() cache.SharedIndexInformer + Lister() PodLister + AddHandler(ctx context.Context, name string, handler PodHandlerFunc) + AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler PodHandlerFunc) + Enqueue(namespace, name string) + Sync(ctx context.Context) error + Start(ctx context.Context, threadiness int) error +} + +type PodInterface interface { + ObjectClient() *objectclient.ObjectClient + Create(*v1.Pod) (*v1.Pod, error) + GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Pod, error) + Get(name string, opts metav1.GetOptions) (*v1.Pod, error) + Update(*v1.Pod) (*v1.Pod, error) + Delete(name string, options *metav1.DeleteOptions) error + DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error + List(opts metav1.ListOptions) (*PodList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error + Controller() PodController + AddHandler(ctx context.Context, name string, sync PodHandlerFunc) + AddLifecycle(ctx context.Context, name string, lifecycle PodLifecycle) + AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync PodHandlerFunc) + AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle PodLifecycle) +} + +type podLister struct { + controller *podController +} + +func (l *podLister) List(namespace string, selector labels.Selector) (ret []*v1.Pod, err error) { + err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { + ret = append(ret, obj.(*v1.Pod)) + }) + return +} + +func (l *podLister) Get(namespace, name string) (*v1.Pod, error) { + var key string + if namespace != "" { + key = namespace + "/" + name + } else { + key = name + } + obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(schema.GroupResource{ + Group: PodGroupVersionKind.Group, + Resource: "pod", + }, key) + } + return obj.(*v1.Pod), nil +} + +type podController struct { + controller.GenericController +} + +func (c *podController) Generic() controller.GenericController { + return c.GenericController +} + +func (c *podController) Lister() PodLister { + return &podLister{ + controller: c, + } +} + +func (c *podController) AddHandler(ctx context.Context, name string, handler PodHandlerFunc) { + c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { + if obj == nil { + return handler(key, nil) + } else if v, ok := obj.(*v1.Pod); ok { + return handler(key, v) + } else { + return nil, nil + } + }) +} + +func (c *podController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler PodHandlerFunc) { + c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { + if obj == nil { + return handler(key, nil) + } else if v, ok := obj.(*v1.Pod); ok && controller.ObjectInCluster(cluster, obj) { + return handler(key, v) + } else { + return nil, nil + } + }) +} + +type podFactory struct { +} + +func (c podFactory) Object() runtime.Object { + return &v1.Pod{} +} + +func (c podFactory) List() runtime.Object { + return &PodList{} +} + +func (s *podClient) Controller() PodController { + s.client.Lock() + defer s.client.Unlock() + + c, ok := s.client.podControllers[s.ns] + if ok { + return c + } + + genericController := controller.NewGenericController(PodGroupVersionKind.Kind+"Controller", + s.objectClient) + + c = &podController{ + GenericController: genericController, + } + + s.client.podControllers[s.ns] = c + s.client.starters = append(s.client.starters, c) + + return c +} + +type podClient struct { + client *Client + ns string + objectClient *objectclient.ObjectClient + controller PodController +} + +func (s *podClient) ObjectClient() *objectclient.ObjectClient { + return s.objectClient +} + +func (s *podClient) Create(o *v1.Pod) (*v1.Pod, error) { + obj, err := s.objectClient.Create(o) + return obj.(*v1.Pod), err +} + +func (s *podClient) Get(name string, opts metav1.GetOptions) (*v1.Pod, error) { + obj, err := s.objectClient.Get(name, opts) + return obj.(*v1.Pod), err +} + +func (s *podClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Pod, error) { + obj, err := s.objectClient.GetNamespaced(namespace, name, opts) + return obj.(*v1.Pod), err +} + +func (s *podClient) Update(o *v1.Pod) (*v1.Pod, error) { + obj, err := s.objectClient.Update(o.Name, o) + return obj.(*v1.Pod), err +} + +func (s *podClient) Delete(name string, options *metav1.DeleteOptions) error { + return s.objectClient.Delete(name, options) +} + +func (s *podClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { + return s.objectClient.DeleteNamespaced(namespace, name, options) +} + +func (s *podClient) List(opts metav1.ListOptions) (*PodList, error) { + obj, err := s.objectClient.List(opts) + return obj.(*PodList), err +} + +func (s *podClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { + return s.objectClient.Watch(opts) +} + +// Patch applies the patch and returns the patched deployment. +func (s *podClient) Patch(o *v1.Pod, patchType types.PatchType, data []byte, subresources ...string) (*v1.Pod, error) { + obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) + return obj.(*v1.Pod), err +} + +func (s *podClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { + return s.objectClient.DeleteCollection(deleteOpts, listOpts) +} + +func (s *podClient) AddHandler(ctx context.Context, name string, sync PodHandlerFunc) { + s.Controller().AddHandler(ctx, name, sync) +} + +func (s *podClient) AddLifecycle(ctx context.Context, name string, lifecycle PodLifecycle) { + sync := NewPodLifecycleAdapter(name, false, s, lifecycle) + s.Controller().AddHandler(ctx, name, sync) +} + +func (s *podClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync PodHandlerFunc) { + s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) +} + +func (s *podClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle PodLifecycle) { + sync := NewPodLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) + s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) +} + +type PodIndexer func(obj *v1.Pod) ([]string, error) + +type PodClientCache interface { + Get(namespace, name string) (*v1.Pod, error) + List(namespace string, selector labels.Selector) ([]*v1.Pod, error) + + Index(name string, indexer PodIndexer) + GetIndexed(name, key string) ([]*v1.Pod, error) +} + +type PodClient interface { + Create(*v1.Pod) (*v1.Pod, error) + Get(namespace, name string, opts metav1.GetOptions) (*v1.Pod, error) + Update(*v1.Pod) (*v1.Pod, error) + Delete(namespace, name string, options *metav1.DeleteOptions) error + List(namespace string, opts metav1.ListOptions) (*PodList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + + Cache() PodClientCache + + OnCreate(ctx context.Context, name string, sync PodChangeHandlerFunc) + OnChange(ctx context.Context, name string, sync PodChangeHandlerFunc) + OnRemove(ctx context.Context, name string, sync PodChangeHandlerFunc) + Enqueue(namespace, name string) + + Generic() controller.GenericController + ObjectClient() *objectclient.ObjectClient + Interface() PodInterface +} + +type podClientCache struct { + client *podClient2 +} + +type podClient2 struct { + iface PodInterface + controller PodController +} + +func (n *podClient2) Interface() PodInterface { + return n.iface +} + +func (n *podClient2) Generic() controller.GenericController { + return n.iface.Controller().Generic() +} + +func (n *podClient2) ObjectClient() *objectclient.ObjectClient { + return n.Interface().ObjectClient() +} + +func (n *podClient2) Enqueue(namespace, name string) { + n.iface.Controller().Enqueue(namespace, name) +} + +func (n *podClient2) Create(obj *v1.Pod) (*v1.Pod, error) { + return n.iface.Create(obj) +} + +func (n *podClient2) Get(namespace, name string, opts metav1.GetOptions) (*v1.Pod, error) { + return n.iface.GetNamespaced(namespace, name, opts) +} + +func (n *podClient2) Update(obj *v1.Pod) (*v1.Pod, error) { + return n.iface.Update(obj) +} + +func (n *podClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return n.iface.DeleteNamespaced(namespace, name, options) +} + +func (n *podClient2) List(namespace string, opts metav1.ListOptions) (*PodList, error) { + return n.iface.List(opts) +} + +func (n *podClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { + return n.iface.Watch(opts) +} + +func (n *podClientCache) Get(namespace, name string) (*v1.Pod, error) { + return n.client.controller.Lister().Get(namespace, name) +} + +func (n *podClientCache) List(namespace string, selector labels.Selector) ([]*v1.Pod, error) { + return n.client.controller.Lister().List(namespace, selector) +} + +func (n *podClient2) Cache() PodClientCache { + n.loadController() + return &podClientCache{ + client: n, + } +} + +func (n *podClient2) OnCreate(ctx context.Context, name string, sync PodChangeHandlerFunc) { + n.loadController() + n.iface.AddLifecycle(ctx, name+"-create", &podLifecycleDelegate{create: sync}) +} + +func (n *podClient2) OnChange(ctx context.Context, name string, sync PodChangeHandlerFunc) { + n.loadController() + n.iface.AddLifecycle(ctx, name+"-change", &podLifecycleDelegate{update: sync}) +} + +func (n *podClient2) OnRemove(ctx context.Context, name string, sync PodChangeHandlerFunc) { + n.loadController() + n.iface.AddLifecycle(ctx, name, &podLifecycleDelegate{remove: sync}) +} + +func (n *podClientCache) Index(name string, indexer PodIndexer) { + err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ + name: func(obj interface{}) ([]string, error) { + if v, ok := obj.(*v1.Pod); ok { + return indexer(v) + } + return nil, nil + }, + }) + + if err != nil { + panic(err) + } +} + +func (n *podClientCache) GetIndexed(name, key string) ([]*v1.Pod, error) { + var result []*v1.Pod + objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + if v, ok := obj.(*v1.Pod); ok { + result = append(result, v) + } + } + + return result, nil +} + +func (n *podClient2) loadController() { + if n.controller == nil { + n.controller = n.iface.Controller() + } +} + +type podLifecycleDelegate struct { + create PodChangeHandlerFunc + update PodChangeHandlerFunc + remove PodChangeHandlerFunc +} + +func (n *podLifecycleDelegate) HasCreate() bool { + return n.create != nil +} + +func (n *podLifecycleDelegate) Create(obj *v1.Pod) (runtime.Object, error) { + if n.create == nil { + return obj, nil + } + return n.create(obj) +} + +func (n *podLifecycleDelegate) HasFinalize() bool { + return n.remove != nil +} + +func (n *podLifecycleDelegate) Remove(obj *v1.Pod) (runtime.Object, error) { + if n.remove == nil { + return obj, nil + } + return n.remove(obj) +} + +func (n *podLifecycleDelegate) Updated(obj *v1.Pod) (runtime.Object, error) { + if n.update == nil { + return obj, nil + } + return n.update(obj) +} diff --git a/types/apis/core/v1/zz_generated_pod_lifecycle_adapter.go b/types/apis/core/v1/zz_generated_pod_lifecycle_adapter.go new file mode 100644 index 0000000000..aa761dedcd --- /dev/null +++ b/types/apis/core/v1/zz_generated_pod_lifecycle_adapter.go @@ -0,0 +1,63 @@ +package v1 + +import ( + "github.com/rancher/norman/lifecycle" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +type PodLifecycle interface { + Create(obj *v1.Pod) (runtime.Object, error) + Remove(obj *v1.Pod) (runtime.Object, error) + Updated(obj *v1.Pod) (runtime.Object, error) +} + +type podLifecycleAdapter struct { + lifecycle PodLifecycle +} + +func (w *podLifecycleAdapter) HasCreate() bool { + o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) + return !ok || o.HasCreate() +} + +func (w *podLifecycleAdapter) HasFinalize() bool { + o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) + return !ok || o.HasFinalize() +} + +func (w *podLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { + o, err := w.lifecycle.Create(obj.(*v1.Pod)) + if o == nil { + return nil, err + } + return o, err +} + +func (w *podLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { + o, err := w.lifecycle.Remove(obj.(*v1.Pod)) + if o == nil { + return nil, err + } + return o, err +} + +func (w *podLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { + o, err := w.lifecycle.Updated(obj.(*v1.Pod)) + if o == nil { + return nil, err + } + return o, err +} + +func NewPodLifecycleAdapter(name string, clusterScoped bool, client PodInterface, l PodLifecycle) PodHandlerFunc { + adapter := &podLifecycleAdapter{lifecycle: l} + syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) + return func(key string, obj *v1.Pod) (runtime.Object, error) { + newObj, err := syncFn(key, obj) + if o, ok := newObj.(runtime.Object); ok { + return o, err + } + return nil, err + } +} diff --git a/types/apis/core/v1/zz_generated_scheme.go b/types/apis/core/v1/zz_generated_scheme.go new file mode 100644 index 0000000000..96f79fcd73 --- /dev/null +++ b/types/apis/core/v1/zz_generated_scheme.go @@ -0,0 +1,41 @@ +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +const ( + GroupName = "" + Version = "v1" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: Version} + +// Kind takes an unqualified kind and returns a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + // TODO this gets cleaned up when the types are fixed + scheme.AddKnownTypes(SchemeGroupVersion, + + &NodeList{}, + &ServiceList{}, + &PodList{}, + ) + return nil +} diff --git a/types/apis/core/v1/zz_generated_service_controller.go b/types/apis/core/v1/zz_generated_service_controller.go new file mode 100644 index 0000000000..36153efab7 --- /dev/null +++ b/types/apis/core/v1/zz_generated_service_controller.go @@ -0,0 +1,441 @@ +package v1 + +import ( + "context" + + "github.com/rancher/norman/controller" + "github.com/rancher/norman/objectclient" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/tools/cache" +) + +var ( + ServiceGroupVersionKind = schema.GroupVersionKind{ + Version: Version, + Group: GroupName, + Kind: "Service", + } + ServiceResource = metav1.APIResource{ + Name: "services", + SingularName: "service", + Namespaced: true, + + Kind: ServiceGroupVersionKind.Kind, + } +) + +func NewService(namespace, name string, obj v1.Service) *v1.Service { + obj.APIVersion, obj.Kind = ServiceGroupVersionKind.ToAPIVersionAndKind() + obj.Name = name + obj.Namespace = namespace + return &obj +} + +type ServiceList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []v1.Service +} + +type ServiceHandlerFunc func(key string, obj *v1.Service) (runtime.Object, error) + +type ServiceChangeHandlerFunc func(obj *v1.Service) (runtime.Object, error) + +type ServiceLister interface { + List(namespace string, selector labels.Selector) (ret []*v1.Service, err error) + Get(namespace, name string) (*v1.Service, error) +} + +type ServiceController interface { + Generic() controller.GenericController + Informer() cache.SharedIndexInformer + Lister() ServiceLister + AddHandler(ctx context.Context, name string, handler ServiceHandlerFunc) + AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler ServiceHandlerFunc) + Enqueue(namespace, name string) + Sync(ctx context.Context) error + Start(ctx context.Context, threadiness int) error +} + +type ServiceInterface interface { + ObjectClient() *objectclient.ObjectClient + Create(*v1.Service) (*v1.Service, error) + GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Service, error) + Get(name string, opts metav1.GetOptions) (*v1.Service, error) + Update(*v1.Service) (*v1.Service, error) + Delete(name string, options *metav1.DeleteOptions) error + DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error + List(opts metav1.ListOptions) (*ServiceList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error + Controller() ServiceController + AddHandler(ctx context.Context, name string, sync ServiceHandlerFunc) + AddLifecycle(ctx context.Context, name string, lifecycle ServiceLifecycle) + AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync ServiceHandlerFunc) + AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle ServiceLifecycle) +} + +type serviceLister struct { + controller *serviceController +} + +func (l *serviceLister) List(namespace string, selector labels.Selector) (ret []*v1.Service, err error) { + err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { + ret = append(ret, obj.(*v1.Service)) + }) + return +} + +func (l *serviceLister) Get(namespace, name string) (*v1.Service, error) { + var key string + if namespace != "" { + key = namespace + "/" + name + } else { + key = name + } + obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(schema.GroupResource{ + Group: ServiceGroupVersionKind.Group, + Resource: "service", + }, key) + } + return obj.(*v1.Service), nil +} + +type serviceController struct { + controller.GenericController +} + +func (c *serviceController) Generic() controller.GenericController { + return c.GenericController +} + +func (c *serviceController) Lister() ServiceLister { + return &serviceLister{ + controller: c, + } +} + +func (c *serviceController) AddHandler(ctx context.Context, name string, handler ServiceHandlerFunc) { + c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { + if obj == nil { + return handler(key, nil) + } else if v, ok := obj.(*v1.Service); ok { + return handler(key, v) + } else { + return nil, nil + } + }) +} + +func (c *serviceController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler ServiceHandlerFunc) { + c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { + if obj == nil { + return handler(key, nil) + } else if v, ok := obj.(*v1.Service); ok && controller.ObjectInCluster(cluster, obj) { + return handler(key, v) + } else { + return nil, nil + } + }) +} + +type serviceFactory struct { +} + +func (c serviceFactory) Object() runtime.Object { + return &v1.Service{} +} + +func (c serviceFactory) List() runtime.Object { + return &ServiceList{} +} + +func (s *serviceClient) Controller() ServiceController { + s.client.Lock() + defer s.client.Unlock() + + c, ok := s.client.serviceControllers[s.ns] + if ok { + return c + } + + genericController := controller.NewGenericController(ServiceGroupVersionKind.Kind+"Controller", + s.objectClient) + + c = &serviceController{ + GenericController: genericController, + } + + s.client.serviceControllers[s.ns] = c + s.client.starters = append(s.client.starters, c) + + return c +} + +type serviceClient struct { + client *Client + ns string + objectClient *objectclient.ObjectClient + controller ServiceController +} + +func (s *serviceClient) ObjectClient() *objectclient.ObjectClient { + return s.objectClient +} + +func (s *serviceClient) Create(o *v1.Service) (*v1.Service, error) { + obj, err := s.objectClient.Create(o) + return obj.(*v1.Service), err +} + +func (s *serviceClient) Get(name string, opts metav1.GetOptions) (*v1.Service, error) { + obj, err := s.objectClient.Get(name, opts) + return obj.(*v1.Service), err +} + +func (s *serviceClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Service, error) { + obj, err := s.objectClient.GetNamespaced(namespace, name, opts) + return obj.(*v1.Service), err +} + +func (s *serviceClient) Update(o *v1.Service) (*v1.Service, error) { + obj, err := s.objectClient.Update(o.Name, o) + return obj.(*v1.Service), err +} + +func (s *serviceClient) Delete(name string, options *metav1.DeleteOptions) error { + return s.objectClient.Delete(name, options) +} + +func (s *serviceClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { + return s.objectClient.DeleteNamespaced(namespace, name, options) +} + +func (s *serviceClient) List(opts metav1.ListOptions) (*ServiceList, error) { + obj, err := s.objectClient.List(opts) + return obj.(*ServiceList), err +} + +func (s *serviceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { + return s.objectClient.Watch(opts) +} + +// Patch applies the patch and returns the patched deployment. +func (s *serviceClient) Patch(o *v1.Service, patchType types.PatchType, data []byte, subresources ...string) (*v1.Service, error) { + obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) + return obj.(*v1.Service), err +} + +func (s *serviceClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { + return s.objectClient.DeleteCollection(deleteOpts, listOpts) +} + +func (s *serviceClient) AddHandler(ctx context.Context, name string, sync ServiceHandlerFunc) { + s.Controller().AddHandler(ctx, name, sync) +} + +func (s *serviceClient) AddLifecycle(ctx context.Context, name string, lifecycle ServiceLifecycle) { + sync := NewServiceLifecycleAdapter(name, false, s, lifecycle) + s.Controller().AddHandler(ctx, name, sync) +} + +func (s *serviceClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync ServiceHandlerFunc) { + s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) +} + +func (s *serviceClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle ServiceLifecycle) { + sync := NewServiceLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) + s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) +} + +type ServiceIndexer func(obj *v1.Service) ([]string, error) + +type ServiceClientCache interface { + Get(namespace, name string) (*v1.Service, error) + List(namespace string, selector labels.Selector) ([]*v1.Service, error) + + Index(name string, indexer ServiceIndexer) + GetIndexed(name, key string) ([]*v1.Service, error) +} + +type ServiceClient interface { + Create(*v1.Service) (*v1.Service, error) + Get(namespace, name string, opts metav1.GetOptions) (*v1.Service, error) + Update(*v1.Service) (*v1.Service, error) + Delete(namespace, name string, options *metav1.DeleteOptions) error + List(namespace string, opts metav1.ListOptions) (*ServiceList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + + Cache() ServiceClientCache + + OnCreate(ctx context.Context, name string, sync ServiceChangeHandlerFunc) + OnChange(ctx context.Context, name string, sync ServiceChangeHandlerFunc) + OnRemove(ctx context.Context, name string, sync ServiceChangeHandlerFunc) + Enqueue(namespace, name string) + + Generic() controller.GenericController + ObjectClient() *objectclient.ObjectClient + Interface() ServiceInterface +} + +type serviceClientCache struct { + client *serviceClient2 +} + +type serviceClient2 struct { + iface ServiceInterface + controller ServiceController +} + +func (n *serviceClient2) Interface() ServiceInterface { + return n.iface +} + +func (n *serviceClient2) Generic() controller.GenericController { + return n.iface.Controller().Generic() +} + +func (n *serviceClient2) ObjectClient() *objectclient.ObjectClient { + return n.Interface().ObjectClient() +} + +func (n *serviceClient2) Enqueue(namespace, name string) { + n.iface.Controller().Enqueue(namespace, name) +} + +func (n *serviceClient2) Create(obj *v1.Service) (*v1.Service, error) { + return n.iface.Create(obj) +} + +func (n *serviceClient2) Get(namespace, name string, opts metav1.GetOptions) (*v1.Service, error) { + return n.iface.GetNamespaced(namespace, name, opts) +} + +func (n *serviceClient2) Update(obj *v1.Service) (*v1.Service, error) { + return n.iface.Update(obj) +} + +func (n *serviceClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return n.iface.DeleteNamespaced(namespace, name, options) +} + +func (n *serviceClient2) List(namespace string, opts metav1.ListOptions) (*ServiceList, error) { + return n.iface.List(opts) +} + +func (n *serviceClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { + return n.iface.Watch(opts) +} + +func (n *serviceClientCache) Get(namespace, name string) (*v1.Service, error) { + return n.client.controller.Lister().Get(namespace, name) +} + +func (n *serviceClientCache) List(namespace string, selector labels.Selector) ([]*v1.Service, error) { + return n.client.controller.Lister().List(namespace, selector) +} + +func (n *serviceClient2) Cache() ServiceClientCache { + n.loadController() + return &serviceClientCache{ + client: n, + } +} + +func (n *serviceClient2) OnCreate(ctx context.Context, name string, sync ServiceChangeHandlerFunc) { + n.loadController() + n.iface.AddLifecycle(ctx, name+"-create", &serviceLifecycleDelegate{create: sync}) +} + +func (n *serviceClient2) OnChange(ctx context.Context, name string, sync ServiceChangeHandlerFunc) { + n.loadController() + n.iface.AddLifecycle(ctx, name+"-change", &serviceLifecycleDelegate{update: sync}) +} + +func (n *serviceClient2) OnRemove(ctx context.Context, name string, sync ServiceChangeHandlerFunc) { + n.loadController() + n.iface.AddLifecycle(ctx, name, &serviceLifecycleDelegate{remove: sync}) +} + +func (n *serviceClientCache) Index(name string, indexer ServiceIndexer) { + err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ + name: func(obj interface{}) ([]string, error) { + if v, ok := obj.(*v1.Service); ok { + return indexer(v) + } + return nil, nil + }, + }) + + if err != nil { + panic(err) + } +} + +func (n *serviceClientCache) GetIndexed(name, key string) ([]*v1.Service, error) { + var result []*v1.Service + objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + if v, ok := obj.(*v1.Service); ok { + result = append(result, v) + } + } + + return result, nil +} + +func (n *serviceClient2) loadController() { + if n.controller == nil { + n.controller = n.iface.Controller() + } +} + +type serviceLifecycleDelegate struct { + create ServiceChangeHandlerFunc + update ServiceChangeHandlerFunc + remove ServiceChangeHandlerFunc +} + +func (n *serviceLifecycleDelegate) HasCreate() bool { + return n.create != nil +} + +func (n *serviceLifecycleDelegate) Create(obj *v1.Service) (runtime.Object, error) { + if n.create == nil { + return obj, nil + } + return n.create(obj) +} + +func (n *serviceLifecycleDelegate) HasFinalize() bool { + return n.remove != nil +} + +func (n *serviceLifecycleDelegate) Remove(obj *v1.Service) (runtime.Object, error) { + if n.remove == nil { + return obj, nil + } + return n.remove(obj) +} + +func (n *serviceLifecycleDelegate) Updated(obj *v1.Service) (runtime.Object, error) { + if n.update == nil { + return obj, nil + } + return n.update(obj) +} diff --git a/types/apis/core/v1/zz_generated_service_lifecycle_adapter.go b/types/apis/core/v1/zz_generated_service_lifecycle_adapter.go new file mode 100644 index 0000000000..37a28afd91 --- /dev/null +++ b/types/apis/core/v1/zz_generated_service_lifecycle_adapter.go @@ -0,0 +1,63 @@ +package v1 + +import ( + "github.com/rancher/norman/lifecycle" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +type ServiceLifecycle interface { + Create(obj *v1.Service) (runtime.Object, error) + Remove(obj *v1.Service) (runtime.Object, error) + Updated(obj *v1.Service) (runtime.Object, error) +} + +type serviceLifecycleAdapter struct { + lifecycle ServiceLifecycle +} + +func (w *serviceLifecycleAdapter) HasCreate() bool { + o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) + return !ok || o.HasCreate() +} + +func (w *serviceLifecycleAdapter) HasFinalize() bool { + o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) + return !ok || o.HasFinalize() +} + +func (w *serviceLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { + o, err := w.lifecycle.Create(obj.(*v1.Service)) + if o == nil { + return nil, err + } + return o, err +} + +func (w *serviceLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { + o, err := w.lifecycle.Remove(obj.(*v1.Service)) + if o == nil { + return nil, err + } + return o, err +} + +func (w *serviceLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { + o, err := w.lifecycle.Updated(obj.(*v1.Service)) + if o == nil { + return nil, err + } + return o, err +} + +func NewServiceLifecycleAdapter(name string, clusterScoped bool, client ServiceInterface, l ServiceLifecycle) ServiceHandlerFunc { + adapter := &serviceLifecycleAdapter{lifecycle: l} + syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) + return func(key string, obj *v1.Service) (runtime.Object, error) { + newObj, err := syncFn(key, obj) + if o, ok := newObj.(runtime.Object); ok { + return o, err + } + return nil, err + } +} diff --git a/types/codegen/main.go b/types/codegen/main.go index cedb918120..be6e2164a8 100644 --- a/types/codegen/main.go +++ b/types/codegen/main.go @@ -5,6 +5,8 @@ import ( v1 "github.com/rancher/k3s/types/apis/k3s.cattle.io/v1" "github.com/rancher/norman/generator" "github.com/sirupsen/logrus" + v13 "k8s.io/api/apps/v1" + v12 "k8s.io/api/core/v1" ) var ( @@ -65,4 +67,19 @@ func main() { if err := generator.DefaultGenerate(v1.Schemas, basePackage, false, nil); err != nil { logrus.Fatal(err) } + + if err := generator.ControllersForForeignTypes(basePackage, v12.SchemeGroupVersion, []interface{}{ + v12.Service{}, + v12.Pod{}, + }, []interface{}{ + v12.Node{}, + }); err != nil { + logrus.Fatal(err) + } + + if err := generator.ControllersForForeignTypes(basePackage, v13.SchemeGroupVersion, []interface{}{ + v13.Deployment{}, + }, nil); err != nil { + logrus.Fatal(err) + } }