...

Source file src/edge-infra.dev/pkg/sds/ien/k8s/controllers/pxe/controller.go

Documentation: edge-infra.dev/pkg/sds/ien/k8s/controllers/pxe

     1  package pxe
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/go-logr/logr"
     7  	v1dnsmasq "github.com/kvaps/dnsmasq-controller/api/v1beta1"
     8  	appsv1 "k8s.io/api/apps/v1"
     9  	corev1 "k8s.io/api/core/v1"
    10  	"k8s.io/apimachinery/pkg/fields"
    11  	"k8s.io/apimachinery/pkg/runtime"
    12  	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
    13  	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
    14  	"k8s.io/client-go/rest"
    15  	ctrl "sigs.k8s.io/controller-runtime"
    16  	"sigs.k8s.io/controller-runtime/pkg/cache"
    17  	"sigs.k8s.io/controller-runtime/pkg/client"
    18  	"sigs.k8s.io/controller-runtime/pkg/manager"
    19  
    20  	"edge-infra.dev/pkg/k8s/runtime/controller"
    21  	edgereconcile "edge-infra.dev/pkg/k8s/runtime/controller/reconcile"
    22  	"edge-infra.dev/pkg/k8s/runtime/patch"
    23  	"edge-infra.dev/pkg/k8s/runtime/sap"
    24  	v1ienode "edge-infra.dev/pkg/sds/ien/k8s/apis/v1"
    25  	v1pxe "edge-infra.dev/pkg/sds/ien/k8s/controllers/pxe/apis/v1"
    26  	"edge-infra.dev/pkg/sds/ien/k8s/controllers/pxe/common"
    27  )
    28  
    29  // +kubebuilder:rbac:groups=dsds.edge.ncr.com,resources=pxes,verbs=get;list;watch;update;patch
    30  // +kubebuilder:rbac:groups=dsds.edge.ncr.com,resources=pxes/status,verbs=get;create;patch;delete
    31  
    32  // +kubebuilder:rbac:groups=dsds.edge.ncr.com,resources=ienodes,verbs=get;list;watch
    33  
    34  // +kubebuilder:rbac:groups=dnsmasq.kvaps.cf,resources=dnsmasqoptions,namespace=pxe,verbs=get;create;update;patch;delete
    35  // +kubebuilder:rbac:groups=dnsmasq.kvaps.cf,resources=dhcphosts;dhcpoptions,namespace=pxe,verbs=get;create;patch;delete
    36  
    37  // +kubebuilder:rbac:groups=dnsmasq.kvaps.cf,resources=dnsmasqoptions,verbs=list;watch
    38  
    39  // +kubebuilder:rbac:groups="",resources=nodes,verbs=get;list;watch
    40  
    41  // +kubebuilder:rbac:groups="",resources=configmaps,resourceNames=boot-options,namespace=pxe,verbs=get
    42  // +kubebuilder:rbac:groups="",resources=configmaps,resourceNames=ipxe-files,namespace=pxe,verbs=get;patch;delete
    43  // +kubebuilder:rbac:groups="",resources=configmaps,resourceNames=static-file-server-config,namespace=pxe,verbs=get;patch
    44  
    45  // +kubebuilder:rbac:groups="",resources=secrets,namespace=pxe,verbs=get
    46  
    47  // +kubebuilder:rbac:groups="",resources=configmaps;secrets;services,verbs=list;watch
    48  
    49  // +kubebuilder:rbac:groups="apps",resources=deployments,resourceNames=dnsmasq-controller;static-file-server,namespace=pxe,verbs=get;patch;delete
    50  // +kubebuilder:rbac:groups="apps",resources=deployments,verbs=list;watch
    51  
    52  // TODO: FIX(10563) Remove this temporary fix in 0.21
    53  // +kubebuilder:rbac:groups="apps",resources=deployments,resourceNames=static-file-server-deployment,namespace=pxe,verbs=get;delete
    54  // +kubebuilder:rbac:groups="",resources=configmaps,resourceNames=static-file-server-configmap,namespace=pxe,verbs=get;delete
    55  
    56  var (
    57  	metricsBindAddress = ":9000" // avoid conflicting with dnsmasq controller binding
    58  	healthBindAddress  = ":9001" // avoid conflicting with dnsmasq controller binding
    59  )
    60  
    61  type Reconciler struct {
    62  	name    string
    63  	client  client.Client
    64  	manager *sap.ResourceManager
    65  }
    66  
    67  // Run the PXE controller
    68  func Run(log logr.Logger, opts ...controller.Option) error {
    69  	ctrl.SetLogger(log)
    70  	opts = append(opts, controller.WithMetricsAddress(metricsBindAddress))
    71  	mgr, err := createManager(opts...)
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	if err := registerControllers(mgr); err != nil {
    77  		return err
    78  	}
    79  
    80  	// TODO: FIX(10563) Remove this temporary fix in 0.21
    81  	ctx := ctrl.LoggerInto(context.Background(), log)
    82  
    83  	key := client.ObjectKey{
    84  		Namespace: common.PXENamespace,
    85  		Name:      "static-file-server-deployment",
    86  	}
    87  
    88  	deploy := &appsv1.Deployment{}
    89  	err = mgr.GetAPIReader().Get(ctx, key, deploy)
    90  	if client.IgnoreNotFound(err) != nil {
    91  		return err
    92  	}
    93  	if err == nil {
    94  		if err := mgr.GetClient().Delete(ctx, deploy); err != nil {
    95  			return err
    96  		}
    97  	}
    98  
    99  	key = client.ObjectKey{
   100  		Namespace: common.PXENamespace,
   101  		Name:      "static-file-server-configmap",
   102  	}
   103  
   104  	cm := &corev1.ConfigMap{}
   105  	err = mgr.GetAPIReader().Get(ctx, key, cm)
   106  	if client.IgnoreNotFound(err) != nil {
   107  		return err
   108  	}
   109  	if err == nil {
   110  		if err := mgr.GetClient().Delete(ctx, cm); err != nil {
   111  			return err
   112  		}
   113  	}
   114  
   115  	// start controllers registered to the manager
   116  	return mgr.Start(ctrl.SetupSignalHandler())
   117  }
   118  
   119  // createManager returns a new controller manager
   120  func createManager(ctrlOpts ...controller.Option) (ctrl.Manager, error) {
   121  	cfg, opts := managerOptions(ctrlOpts...)
   122  
   123  	return ctrl.NewManager(cfg, opts)
   124  }
   125  
   126  // managerOptions returns the rest configuration and manager options for the
   127  // controller manager
   128  func managerOptions(ctrlOpts ...controller.Option) (*rest.Config, manager.Options) {
   129  	cfg, opts := controller.ProcessOptions(ctrlOpts...)
   130  	opts.Scheme = scheme()
   131  	opts.HealthProbeBindAddress = healthBindAddress
   132  	opts.Cache = cacheOptions()
   133  
   134  	return cfg, opts
   135  }
   136  
   137  // cacheOptions returns cache options that ensure that only the resources that
   138  // PXE controller needs to work with are cached
   139  func cacheOptions() cache.Options {
   140  	return cache.Options{
   141  		ByObject: map[client.Object]cache.ByObject{
   142  			&v1pxe.PXE{}: {
   143  				Field: fields.Everything(),
   144  			},
   145  			&v1ienode.IENode{}: {
   146  				Field: fields.Everything(),
   147  			},
   148  			&corev1.Node{}: {
   149  				Field: fields.Everything(),
   150  			},
   151  			&corev1.ConfigMap{}: {
   152  				Field: fields.SelectorFromSet(fields.Set{
   153  					"metadata.namespace": common.PXENamespace,
   154  				}),
   155  			},
   156  			&corev1.Secret{}: {
   157  				Field: fields.SelectorFromSet(fields.Set{
   158  					"metadata.namespace": common.PXENamespace,
   159  				}),
   160  			},
   161  			&appsv1.Deployment{}: {
   162  				Field: fields.SelectorFromSet(fields.Set{
   163  					"metadata.namespace": common.PXENamespace,
   164  				}),
   165  			},
   166  			&v1dnsmasq.DnsmasqOptions{}: {
   167  				Field: fields.SelectorFromSet(fields.Set{
   168  					"metadata.namespace": common.PXENamespace,
   169  				}),
   170  			},
   171  			&v1dnsmasq.DhcpHosts{}: {
   172  				Field: fields.SelectorFromSet(fields.Set{
   173  					"metadata.namespace": common.PXENamespace,
   174  				}),
   175  			},
   176  			&v1dnsmasq.DhcpOptions{}: {
   177  				Field: fields.SelectorFromSet(fields.Set{
   178  					"metadata.namespace": common.PXENamespace,
   179  				}),
   180  			},
   181  		},
   182  	}
   183  }
   184  
   185  // registerControllers registers the PXE reconcilers to the controller manager
   186  func registerControllers(mgr ctrl.Manager) error {
   187  	client := mgr.GetClient()
   188  
   189  	scaler, err := NewScaler(mgr, client)
   190  	if err != nil {
   191  		return err
   192  	}
   193  	if err := scaler.SetupWithManager(mgr); err != nil {
   194  		return err
   195  	}
   196  
   197  	provisioner, err := NewProvisioner(mgr, client)
   198  	if err != nil {
   199  		return err
   200  	}
   201  	return provisioner.SetupWithManager(mgr)
   202  }
   203  
   204  // scheme returns a scheme with the default schema as well as the iennode and
   205  // dnsmasq custom resources registered
   206  func scheme() *runtime.Scheme {
   207  	scheme := runtime.NewScheme()
   208  	utilruntime.Must(clientgoscheme.AddToScheme(scheme))
   209  	utilruntime.Must(v1ienode.AddToScheme(scheme))
   210  	utilruntime.Must(v1pxe.AddToScheme(scheme))
   211  	utilruntime.Must(v1dnsmasq.AddToScheme(scheme))
   212  
   213  	return scheme
   214  }
   215  
   216  // summarize summarizes the result of the reconcile and patches the pxe object
   217  func (r *Reconciler) summarize(ctx context.Context, patcher *patch.SerialPatcher, pxe *v1pxe.PXE, recErr error) (ctrl.Result, error) {
   218  	s := edgereconcile.NewSummarizer(patcher)
   219  	return s.SummarizeAndPatch(ctx, pxe,
   220  		edgereconcile.WithResult(edgereconcile.ResultEmpty),
   221  		edgereconcile.WithError(recErr),
   222  		edgereconcile.WithProcessors(
   223  			edgereconcile.RecordReconcileReq,
   224  			edgereconcile.RecordResult,
   225  		),
   226  		edgereconcile.WithFieldOwner(r.name),
   227  	)
   228  }
   229  

View as plain text