### Install Project using kubectl Source: https://github.com/nephio-project/nephio/blob/main/operators/focom-operator/README.md Demonstrates how users can install the project by applying the generated 'install.yaml' file using kubectl. This file contains all necessary resources for installation. ```sh kubectl apply -f https://raw.githubusercontent.com//focom-operator//dist/install.yaml ``` -------------------------------- ### Build Installer Command Source: https://github.com/nephio-project/nephio/blob/main/operators/focom-operator/README.md This command is used to build the installer for the operator image, which includes Kustomize-built resources necessary for project installation. ```sh make build-installer IMG=/focom-operator:tag ``` -------------------------------- ### Detailed Reconcile Flow Example Source: https://github.com/nephio-project/nephio/blob/main/operators/focom-operator/README.md Provides a more granular example of the reconciliation flow, illustrating conditional logic and the role of helper methods like handleDeletion. ```text Fetch CR → if not found, done. If being deleted → handleDeletion(...) → done. If no finalizer → add finalizer → requeue. Validate → if invalid, set status → done. Build remote → if fails, set status → done. Ensure remote resource (create or poll) → set status → requeue if needed ``` -------------------------------- ### Nephio Controller Manager Setup and Configuration (Go) Source: https://context7.com/nephio-project/nephio/llms.txt Sets up and configures the Nephio Controller Manager, initializing reconcilers, and integrating with IPAM/VLAN backends. It uses the controller-runtime library and supports various command-line flags for enabling specific reconcilers and configuring backend addresses. ```go package main import ( "context" "os" "github.com/nephio-project/nephio/controllers/pkg/reconcilers/config" "github.com/nokia/k8s-ipam/pkg/proxy/clientproxy" "github.com/nokia/k8s-ipam/pkg/proxy/clientproxy/ipam" "github.com/nokia/k8s-ipam/pkg/proxy/clientproxy/vlan" ctrl "sigs.k8s.io/controller-runtime" ) func main() { ctx := context.Background() // Configure controller manager with reconcilers mgr, _ := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ Scheme: scheme, Metrics: server.Options{BindAddress: ":8080"}, HealthProbeBindAddress: ":8081", LeaderElection: false, LeaderElectionID: "nephio-operators.nephio.org", }) // Backend configuration for IPAM and VLAN backendAddress := os.Getenv("CLIENT_PROXY_ADDRESS") if backendAddress == "" { backendAddress = "127.0.0.1:9999" } // Controller configuration ctrlCfg := &config.ControllerConfig{ Address: backendAddress, PorchClient: porchClient, PorchRESTClient: porchRESTClient, IpamClientProxy: ipam.New(ctx, clientproxy.Config{ Address: backendAddress, }), VlanClientProxy: vlan.New(ctx, clientproxy.Config{ Address: backendAddress, }), ApprovalRequeueDuration: 15, } // Start with enabled reconcilers mgr.Start(ctx) } // Command line usage: // # Enable all reconcilers // ./controller-manager --reconcilers=* --metrics-bind-address=:8080 // // # Enable specific reconcilers // ./controller-manager --reconcilers=approval,network,repository // // # Configure IPAM backend // export CLIENT_PROXY_ADDRESS="ipam-service.nephio-system:9999" // ./controller-manager --reconcilers=* // // Available reconcilers: // - approval: Auto-approves package revisions // - bootstrap-packages: Bootstraps initial packages // - bootstrap-secret: Manages bootstrap secrets // - generic-specializer: Runs KRM functions on packages // - network: Manages network resources // - repository: Manages Porch repositories // - spire-bootstrap: Manages SPIRE security // - token: Manages authentication tokens ``` -------------------------------- ### Example Environment Variables for Gitea Connection Source: https://github.com/nephio-project/nephio/blob/main/controllers/pkg/reconcilers/token/README.md This snippet shows example environment variables used to configure the token controller's connection to the Gitea server. It includes the mandatory GIT_URL and optionally GIT_SECRET_NAME and GIT_NAMESPACE for custom secret configurations. ```yaml - name: "GIT_URL" value: "https://172.18.0.200:3000" ``` -------------------------------- ### Example Token CRD with Application Annotation Source: https://github.com/nephio-project/nephio/blob/main/controllers/pkg/reconcilers/token/README.md This YAML example illustrates the creation of a Token CRD with an annotation specifying the associated application. This particular instance is for 'mgmt-access-token-configsync' and is linked to the 'configsync' application. ```yaml cat < Published // Error if lifecycle is not Proposed or already at target state } ``` -------------------------------- ### Setting Status and Returning Results in Go Source: https://github.com/nephio-project/nephio/blob/main/krm-functions/lib/condkptsdk/design.md This final Go snippet demonstrates how to set the status of an interface using an error-handling mechanism and return the updated Kubernetes object along with any potential errors. This is a standard pattern for completing operations in Go. ```go // set the status err = itfceKOE.SetStatus(itfce) return &itfceKOE.KubeObject, err } ``` -------------------------------- ### Allocate IP Address with Nephio IPAM Function (Go) Source: https://context7.com/nephio-project/nephio/llms.txt Demonstrates how to use the Nephio IPAM function client to claim an IPv4 prefix for a network interface. It requires the kptdev/krm-functions-sdk and nokia/k8s-ipam libraries. The function takes a context and an IPClaim object, and returns an IPAM response containing the allocated prefix and gateway. ```go package main import ( "context" "github.com/kptdev/krm-functions-sdk/go/fn" ipamv1alpha1 "github.com/nokia/k8s-ipam/apis/resource/ipam/v1alpha1" "github.com/nokia/k8s-ipam/pkg/proxy/clientproxy/ipam" resourcev1alpha1 "github.com/nokia/k8s-ipam/apis/resource/common/v1alpha1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func main() { // Create IPAM client proxy clientProxy := ipam.New(context.Background(), clientproxy.Config{ Address: "127.0.0.1:9999", }) // Create IP claim for network interface claim := ipamv1alpha1.BuildIPClaim( metav1.ObjectMeta{ Name: "upf-n3-ipv4", Annotations: map[string]string{ resourcev1alpha1.NephioClusterNameKey: "edge-cluster-01", }, }, ipamv1alpha1.IPClaimSpec{ Kind: ipamv1alpha1.PrefixKindNetwork, NetworkInstance: corev1.ObjectReference{ Name: "vpc-ran", }, ClaimLabels: resourcev1alpha1.ClaimLabels{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{ resourcev1alpha1.NephioClusterNameKey: "edge-cluster-01", resourcev1alpha1.NephioAddressFamilyKey: "ipv4", resourcev1alpha1.NephioNetworkNameKey: "n3", }, }, }, }, ipamv1alpha1.IPClaimStatus{}, ) // Claim IP address from IPAM backend resp, err := clientProxy.Claim(context.Background(), claim, nil) if err != nil { panic(err) } // Expected output: resp.Status.Prefix = "10.0.1.0/24" // Expected output: resp.Status.Gateway = "10.0.1.1" } ``` -------------------------------- ### Run Nephio Controller with Owns Configuration (Golang) Source: https://github.com/nephio-project/nephio/blob/main/krm-functions/lib/condkptsdk/design.md This Go function demonstrates the initialization and execution of a Nephio controller. It configures the controller with 'owns' rules for managing dependent resources like NetworkAttachmentDefinitions and IPClaims, and 'watch' rules for observing WorkloadCluster resources. The function utilizes the condkptsdk for Kubernetes dynamic control plane operations. ```golang package main import ( "fmt" "reflect" "github.com/nephio-project/api/ipam/v1alpha1" "github.com/nephio-project/api/nephio/v1alpha1" "github.com/nephio-project/nephio/internal/ipclaim" "github.com/nephio-project/nephio/internal/ko" "github.com/nephio-project/nephio/internal/log" "github.com/nephio-project/nephio/internal/meta" "github.com/nephio-project/nephio/internal/networkattachmentdefinition" "github.com/nephio-project/nephio/internal/vlanclaim" infrav1alpha1 "github.com/nephio-project/nephio/internal/workloadcluster/api/v1alpha1" "github.com/nephio-project/nephio/pkg/condkptsdk" "github.com/nephio-project/nephio/pkg/fn" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const defaultPODNetwork = "pod" type itfceFn struct { sdk condkptsdk.KptCondSDK workloadCluster *infrav1alpha1.WorkloadCluster } func Run(rl *fn.ResourceList) (bool, error) { myFn := itfceFn{} var err error myFn.sdk, err = condkptsdk.New( rl, &condkptsdk.Config{ For: corev1.ObjectReference{ APIVersion: nephioreqv1alpha1.GroupVersion.Identifier(), Kind: nephioreqv1alpha1.InterfaceKind, }, Owns: map[corev1.ObjectReference]condkptsdk.ResourceKind{ { APIVersion: nadv1.SchemeGroupVersion.Identifier(), Kind: reflect.TypeOf(nadv1.NetworkAttachmentDefinition{}).Name(), }: condkptsdk.ChildRemoteCondition, { APIVersion: ipamv1alpha1.GroupVersion.Identifier(), Kind: ipamv1alpha1.IPClaimKind, }: condkptsdk.ChildRemote, { APIVersion: vlanv1alpha1.GroupVersion.Identifier(), Kind: vlanv1alpha1.VLANClaimKind, }: condkptsdk.ChildRemote, }, Watch: map[corev1.ObjectReference]condkptsdk.WatchCallbackFn{ { APIVersion: infrav1alpha1.GroupVersion.Identifier(), Kind: reflect.TypeOf(infrav1alpha1.WorkloadCluster{}).Name(), }: myFn.WorkloadClusterCallbackFn, }, PopulateOwnResourcesFn: myFn.desiredOwnedResourceList, UpdateResourceFn: myFn.updateItfceResource, }, ) if err != nil { rl.Results.ErrorE(err) return false, err } return myFn.sdk.Run() } // WorkloadClusterCallbackFn provides a callback for the workload cluster // resources in the resourceList func (f *itfceFn) WorkloadClusterCallbackFn(o *fn.KubeObject) error { var err error if f.workloadCluster != nil { return fmt.Errorf("multiple WorkloadCluster objects found in the kpt package") } f.workloadCluster, err = ko.KubeObjectToStruct[infrav1alpha1.WorkloadCluster](o) if err != nil { return err } // validate check the specifics of the spec, like mandatory fields return f.workloadCluster.Spec.Validate() } // desiredOwnedResourceList returns with the list of all child KubeObjects // belonging to the parent Interface "for object" func (f *itfceFn) desiredOwnedResourceList(o *fn.KubeObject) (fn.KubeObjects, error) { if f.workloadCluster == nil { // no WorkloadCluster resource in the package return nil, fmt.Errorf("workload cluster is missing from the kpt package") } // resources contain the list of child resources // belonging to the parent object resources := fn.KubeObjects{} itfceKOE, err := ko.NewFromKubeObject[nephioreqv1alpha1.Interface](o) if err != nil { return nil, err } itfce, err := itfceKOE.GetGoStruct() if err != nil { return nil, err } // Nothing to be done in case the interface is attached to // the default pod network since this is all handled in the // k8s cluster via the CNI. if itfce.Spec.NetworkInstance.Name == defaultPODNetwork { return fn.KubeObjects{}, nil } // meta is the generic object meta attached to all derived child objects meta := metav1.ObjectMeta{ Name: o.GetName(), Annotations: getAnnotations(o.GetAnnotations()), } afs := getAddressFamilies(itfce.Spec.IpFamilyPolicy) // When the CNIType is not set this is a loopback interface if itfce.Spec.CNIType != "" { if !f.IsCNITypePresent(itfce.Spec.CNIType) { return nil, fmt.Errorf("cniType not supported in workload cluster; workload cluster CNI(s): %v, interface cniType requested: %s", f.workloadCluster.Spec.CNIs, itfce.Spec.CNIType) } // add IPClaim of type network for _, af := range afs { meta := metav1.ObjectMeta{ Name: fmt.Sprintf("%s-%s", o.GetName(), string(af)), Annotations: getAnnotations(o.GetAnnotations()), } o, err := f.getIPClaim(meta, *itfce.Spec.NetworkInstance, ipamv1alpha1.PrefixKindNetwork, af) if err != nil { return nil, err } resources = append(resources, o) } if itfce.Spec.AttachmentType == nephioreqv1alpha1.AttachmentTypeVLAN { // add VLANClaim meta := metav1.ObjectMeta{ Name: o.GetName(), Annotations: f.getAnnotationsWithvlanClaimName(itfce), } o, err := f.getVLANClaim(meta) if err != nil { return nil, err } resources = append(resources, o) } // claim nad o, err = f.getNAD(meta) if err != nil { return nil, err } resources = append(resources, o) } else { // add IPClaim of type loopback for _, af := range afs { meta := metav1.ObjectMeta{ Name: fmt.Sprintf("%s-%s", o.GetName(), string(af)), Annotations: getAnnotations(o.GetAnnotations()), } o, err := f.getIPClaim(meta, *itfce.Spec.NetworkInstance, ipamv1alpha1.PrefixKindLoopback, af) if err != nil { return nil, err } resources = append(resources, o) } } return resources, nil } func (f *itfceFn) updateItfceResource(forObj *fn.KubeObject) (*fn.KubeObject, error) { if forObj == nil { return nil, fmt.Errorf("expected a for object but got nil") } itfceKOE, err := ko.NewFromKubeObject[nephioreqv1alpha1.Interface](forObj) ``` -------------------------------- ### Kpt Eval Command for ipam-fn Source: https://github.com/nephio-project/nephio/blob/main/krm-functions/ipam-fn/README.md Shows how to use the kpt eval command to run the ipam-fn as a mutator. This command requires specifying the ipam-container-image. ```bash kpt fn eval --type mutator -i ``` -------------------------------- ### Return Kubernetes Object in Go Source: https://github.com/nephio-project/nephio/blob/main/krm-functions/lib/condkptsdk/design.md This Go code snippet demonstrates how to return a Kubernetes object along with a potential error. It is typically used within functions that interact with Kubernetes resources. ```go } } return &nad.K.KubeObject, nil } ``` -------------------------------- ### Processing VLAN Claims in Go Source: https://github.com/nephio-project/nephio/blob/main/krm-functions/lib/condkptsdk/design.md This Go code snippet iterates through VLAN claims, converts each to a Go struct, and updates the interface status with VLAN claim information. It demonstrates how to handle different types of claims within the same processing flow. ```go vlanclaims := objs.Where(fn.IsGroupVersionKind(vlanv1alpha1.VLANClaimGroupVersionKind)) for _, vlanclaim := range vlanclaims { claim, err := ko.NewFromKubeObject[vlanv1alpha1.VLANClaim](vlanclaim) if err != nil { return nil, err } claimGoStruct, err := claim.GetGoStruct() if err != nil { return nil, err } itfce.Status.VLANClaimStatus = &claimGoStruct.Status } ``` -------------------------------- ### Reconcile Method Flowchart Source: https://github.com/nephio-project/nephio/blob/main/operators/focom-operator/README.md Describes the high-level steps involved in the reconciliation process. It details the sequence of operations from fetching resources to ensuring remote resource creation or polling. ```text fetch → handle deletion → ensure finalizer → validate → build remote → ensure remote. ``` -------------------------------- ### Error Handling and Data Retrieval in Go Source: https://github.com/nephio-project/nephio/blob/main/krm-functions/lib/condkptsdk/design.md This snippet demonstrates a common Go pattern for handling errors after an operation and retrieving a Go struct from a Kubernetes object. It's crucial for robust API interactions and data processing within the application. ```go if err != nil { return nil, err } itfce, err := itfceKOE.GetGoStruct() if err != nil { return nil, err } ``` -------------------------------- ### PackageVariant Configuration for upsert-kustomize-res Source: https://github.com/nephio-project/nephio/blob/main/krm-functions/gen-kustomize-res/README.md This YAML configuration illustrates how to use the `upsert-kustomize-res` function within a `PackageVariant` resource. It specifies the function's image and implies its inclusion in the mutation pipeline for downstream packages. Note the cautionary comment regarding potential prepend behavior affecting pipeline order. ```yaml apiVersion: config.porch.kpt.dev/v1alpha1 kind: PackageVariant metadata: name: example spec: upstream: repo: catalog package: blueprint revision: v1 downstream: repo: deployments pipeline: mutators: - image: docker.io/nephio/gen-kustomize-res:v1 ``` -------------------------------- ### Processing IP Claims and Sorting in Go Source: https://github.com/nephio-project/nephio/blob/main/krm-functions/lib/condkptsdk/design.md This Go code snippet processes IP claims, filters them by group version kind, and sorts them by name. It then iterates through the sorted claims, converting each to a Go struct and updating the interface status with IP allocation information. ```go ipclaims := objs.Where(fn.IsGroupVersionKind(ipamv1alpha1.IPClaimGroupVersionKind)) sort.Slice(ipclaims, func(i, j int) bool { return ipclaims[i].GetName() < ipclaims[j].GetName() }) for _, ipclaim := range ipclaims { // Don't care about the name since the condSDK sorts the data // based on owner reference claim, err := ko.NewFromKubeObject[ipamv1alpha1.IPClaim](ipclaim) if err != nil { return nil, err } claimGoStruct, err := claim.GetGoStruct() if err != nil { return nil, err } itfce.Status.UpsertIPAllocation(claimGoStruct.Status) } ``` -------------------------------- ### Run dnn-fn with kpt fn source Source: https://github.com/nephio-project/nephio/blob/main/krm-functions/dnn-fn/README.md This command pipes the KRM resource package to the dnn-fn Go executable for processing. It's a common pattern for applying KRM functions directly. ```bash kpt fn source | go run main.go ```