Add embedded service load balancer

This commit is contained in:
Darren Shepherd 2019-02-01 22:09:11 -07:00
parent 24463d4985
commit e832588662
22 changed files with 2900 additions and 13 deletions

View File

@ -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.

View File

@ -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",

View File

@ -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"
}

View File

@ -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

View File

@ -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
}

327
pkg/servicelb/controller.go Normal file
View File

@ -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
}

View File

@ -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 "$@"

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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,
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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,
}
}

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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)
}
}