From e657fdf385098067af32fb3ecc3c5fc0c1b5ec16 Mon Sep 17 00:00:00 2001 From: Vamshi Namilikonda Date: Thu, 4 Jan 2024 21:28:28 +0530 Subject: [PATCH] =?UTF-8?q?NFDeployment=20CRD=20for=20Multi-vendor(https:/?= =?UTF-8?q?/github.com/nephio-project/n=E2=80=A6=20(#45)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NFDeployment CRD for Multi-vendor Network functions https://github.com/nephio-project/nephio/issues/400 https://github.com/nephio-project/nephio/issues/401 https://github.com/nephio-project/nephio/issues/402 --- .../workload.nephio.org_nfdeployments.yaml | 404 ++++++++++++++++++ config/crd/kustomization.yaml | 4 +- config/rbac/role.yaml | 56 +-- .../workload_v1alpha1_upfdeployment.yaml | 2 +- controllers/{ => nf}/amf/reconciler.go | 25 +- controllers/{ => nf}/amf/resources.go | 36 +- controllers/{ => nf}/amf/resources_test.go | 54 ++- controllers/{ => nf}/amf/status.go | 27 +- controllers/{ => nf}/amf/status_test.go | 98 ++--- controllers/{ => nf}/amf/templates.go | 0 controllers/nf/reconciler.go | 109 +++++ controllers/{ => nf}/smf/reconciler.go | 46 +- controllers/{ => nf}/smf/resources.go | 20 +- controllers/{ => nf}/smf/resources_test.go | 72 ++-- controllers/{ => nf}/smf/status.go | 2 +- controllers/{ => nf}/smf/status_test.go | 12 +- controllers/{ => nf}/smf/templates.go | 0 controllers/{ => nf}/upf/reconciler.go | 66 ++- controllers/{ => nf}/upf/resources.go | 10 +- controllers/{ => nf}/upf/resources_test.go | 54 ++- controllers/{ => nf}/upf/status.go | 27 +- controllers/{ => nf}/upf/status_test.go | 102 ++--- controllers/{ => nf}/upf/templates.go | 0 free5gc-operator/main.go | 34 +- go.mod | 3 +- go.sum | 2 + test/amf1-n2.yaml | 2 +- test/amf1.yaml | 7 +- test/configref1.yaml | 2 +- test/smf1-n4.yaml | 4 +- test/smf1.yaml | 18 +- test/upf1-n3.yaml | 2 +- test/upf1-n4.yaml | 2 +- test/upf1-n6.yaml | 2 +- test/upf1.yaml | 21 +- test/upf2-n3.yaml | 2 +- test/upf2-n4.yaml | 2 +- test/upf2-n6.yaml | 4 +- 38 files changed, 854 insertions(+), 479 deletions(-) create mode 100644 config/crd/bases/workload.nephio.org_nfdeployments.yaml rename controllers/{ => nf}/amf/reconciler.go (86%) rename controllers/{ => nf}/amf/resources.go (83%) rename controllers/{ => nf}/amf/resources_test.go (82%) rename controllers/{ => nf}/amf/status.go (71%) rename controllers/{ => nf}/amf/status_test.go (69%) rename controllers/{ => nf}/amf/templates.go (100%) create mode 100644 controllers/nf/reconciler.go rename controllers/{ => nf}/smf/reconciler.go (80%) rename controllers/{ => nf}/smf/resources.go (92%) rename controllers/{ => nf}/smf/resources_test.go (89%) rename controllers/{ => nf}/smf/status.go (97%) rename controllers/{ => nf}/smf/status_test.go (96%) rename controllers/{ => nf}/smf/templates.go (100%) rename controllers/{ => nf}/upf/reconciler.go (68%) rename controllers/{ => nf}/upf/resources.go (94%) rename controllers/{ => nf}/upf/resources_test.go (91%) rename controllers/{ => nf}/upf/status.go (71%) rename controllers/{ => nf}/upf/status_test.go (69%) rename controllers/{ => nf}/upf/templates.go (100%) diff --git a/config/crd/bases/workload.nephio.org_nfdeployments.yaml b/config/crd/bases/workload.nephio.org_nfdeployments.yaml new file mode 100644 index 0000000..58880a4 --- /dev/null +++ b/config/crd/bases/workload.nephio.org_nfdeployments.yaml @@ -0,0 +1,404 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + name: nfdeployments.workload.nephio.org +spec: + group: workload.nephio.org + names: + kind: NFDeployment + listKind: NFDeploymentList + plural: nfdeployments + singular: nfdeployment + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + provider: + description: + "Provider defines which provider implement this NFDeployment" + type: string + capacity: + description: capacity defines the capacity characteristics of the + NF deployment + properties: + maxDownlinkThroughput: + anyOf: + - type: integer + - type: string + description: MaxDownlinkThroughput defines the max downlink dataplane + throughput + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + maxNFConnections: + description: MaxNFConnections defines the max NF(s) that can be + connected to this NF/device + type: integer + maxSessions: + description: MaxSessions defines the max sessions of the control + plane expressed in unit of 1000s + type: integer + maxSubscribers: + description: MaxSubscribers defines the max subscribers expressed + in unit of 1000s + type: integer + maxUplinkThroughput: + anyOf: + - type: integer + - type: string + description: MaxUplinkThroughput defines the max uplink dataplane + throughput + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + parametersRefs: + description: configRef defines addiitonal configuration references + the nf depends upon + items: + description: "ObjectReference contains enough information to let + you inspect or modify the referred object. --- New uses of this + type are discouraged because of difficulty describing its usage + when embedded in APIs. 1. Ignored fields. It includes many fields + which are not generally honored. For instance, ResourceVersion + and FieldPath are both very rarely valid in actual usage. 2. Invalid + usage help. It is impossible to add specific help for individual + usage. In most embedded usages, there are particular restrictions + like, \"must refer only to types A and B\" or \"UID not honored\" + or \"name must be restricted\". Those cannot be well described + when embedded. 3. Inconsistent validation. Because the usages + are different, the validation rules are different by usage, which + makes it hard for users to predict what will happen. 4. The fields + are both imprecise and overly precise. Kind is not a precise + mapping to a URL. This can produce ambiguity during interpretation + and require a REST mapping. In most cases, the dependency is + on the group,resource tuple and the version of the actual struct + is irrelevant. 5. We cannot easily change it. Because this type + is embedded in many locations, updates to this type will affect + numerous schemas. Don't make new APIs embed an underspecified + API type they do not control. \n Instead of using this type, create + a locally provided and used type that is well-focused on your + reference. For example, ServiceReferences for admission registration: + https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 + ." + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + interfaces: + description: Interfaces defines the interfaces associated with the + NF deployment + items: + description: InterfaceConfig defines the configuration of the interface + properties: + ipv4: + description: IPv4 defines the ipv4 configuration of the interface + properties: + address: + description: Address defines the IPv4 address and prefix + length in CIDR notation [IP prefix, range IPv4 with host + bits] + type: string + gateway: + description: Gateway defines the IPv4 address associated + to the interface as a gateway + type: string + required: + - address + type: object + ipv6: + description: IPv6Config defines the ipv6 configuration of the + interface + properties: + address: + description: Address defines the IPv6 address and prefix + length in CIDR notation [IP prefix, range IPv6 with host + bits] + type: string + gateway: + description: Gateway defines the IPv6 address associated + to the interface as a gateway + type: string + required: + - address + type: object + name: + description: Name defines the name of the interface + maxLength: 253 + minLength: 1 + type: string + vlanID: + description: VLANID defines the specific vlan id associated + on this interface + type: integer + required: + - name + type: object + type: array + networkInstances: + description: NetworkInstances defines the network instances associated + with the NF deployment + items: + description: A networkInstance is a Layer 3 forwarding construct + such as a virtual routing and forwarding (VRF) instance, + properties: + bgp: + description: BGP defines the BGP configuration associated with + the network instance + properties: + autonomousSystem: + description: AutonomousSystem defines the AS number of the + bgp process + type: integer + bgpNeighbors: + description: BGPNeigbors defines the configuration of the + BGP neighbor + items: + properties: + address: + description: Address defines the IPv4 or IPv6 address + of the BGP neighbor + type: string + name: + description: BGP interface name, MUST match the one + use in InterfaceConfig + type: string + peerAS: + description: PeerAS defines the AS number of the bgp + peer + type: integer + required: + - address + - peerAS + type: object + type: array + routerID: + description: RouterID defines the router ID of the bgp process + type: string + required: + - autonomousSystem + - bgpNeighbors + - routerID + type: object + dataNetworks: + description: DataNetworks defines the data networks assocated + with the network instance + items: + description: A DataNetwork defines the Data Network name defined + by 3GPP + properties: + name: + description: Name defines the name of the data network + maxLength: 253 + minLength: 1 + type: string + pool: + description: Pool defines the list of address pools associated + with the data network + items: + properties: + prefix: + description: Prefix defines the ip cidr in prefix + notation. It is defines as a subnet + pattern: (([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))|((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8]))) + type: string + required: + - prefix + type: object + type: array + type: object + type: array + interfaces: + description: interfaces defines the interfaces associated with + the network instance + items: + type: string + type: array + name: + description: Name defines the name of the network instance + maxLength: 253 + minLength: 1 + type: string + peers: + description: Peers defines the peer configuration associated + with the network instance + items: + description: A PeerConfig defines the peer configuration + properties: + ipv4: + description: IPv4 defines the ipv4 configuration of the + peer + properties: + address: + description: Address defines the IPv4 address and + prefix length in CIDR notation [IP prefix, range + IPv4 with host bits] + type: string + gateway: + description: Gateway defines the IPv4 address associated + to the interface as a gateway + type: string + required: + - address + type: object + ipv6: + description: IPv6 defines the ipv6 configuration of the + peer + properties: + address: + description: Address defines the IPv6 address and + prefix length in CIDR notation [IP prefix, range + IPv6 with host bits] + type: string + gateway: + description: Gateway defines the IPv6 address associated + to the interface as a gateway + type: string + required: + - address + type: object + name: + description: Name defines the name of the data network + maxLength: 253 + minLength: 1 + type: string + type: object + type: array + required: + - name + type: object + type: array + type: object + status: + properties: + conditions: + description: Conditions define the current state of the NF deployment + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + observedGeneration: + description: The generation observed by the deployment controller. + format: int32 + type: integer + required: + - observedGeneration + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index f63a315..f9b4c6d 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -2,9 +2,7 @@ # since it depends on service name and namespace that are out of this kustomize package. # It should be run by config/default resources: - - bases/workload.nephio.org_amfdeployments.yaml - - bases/workload.nephio.org_smfdeployments.yaml - - bases/workload.nephio.org_upfdeployments.yaml + - bases/workload.nephio.org_nfdeployments.yaml #+kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 24a8d59..91ae0cb 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -4,18 +4,6 @@ kind: ClusterRole metadata: name: free5gc-operator-role rules: -- apiGroups: - - "" - resources: - - configmaps - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - apiGroups: - "" resources: @@ -73,47 +61,7 @@ rules: - apiGroups: - workload.nephio.org resources: - - amfdeployments - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - workload.nephio.org - resources: - - amfdeployments/status - verbs: - - get - - patch - - update -- apiGroups: - - workload.nephio.org - resources: - - smfdeployments - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - workload.nephio.org - resources: - - smfdeployments/status - verbs: - - get - - patch - - update -- apiGroups: - - workload.nephio.org - resources: - - upfdeployments + - nfdeployments verbs: - create - delete @@ -125,7 +73,7 @@ rules: - apiGroups: - workload.nephio.org resources: - - upfdeployments/status + - nfdeployments/status verbs: - get - patch diff --git a/config/samples/workload_v1alpha1_upfdeployment.yaml b/config/samples/workload_v1alpha1_upfdeployment.yaml index 2e666e6..f639467 100644 --- a/config/samples/workload_v1alpha1_upfdeployment.yaml +++ b/config/samples/workload_v1alpha1_upfdeployment.yaml @@ -1,5 +1,5 @@ apiVersion: workload.nephio.org/v1alpha1 -kind: UPFDeployment +kind: NFDeployment metadata: labels: app.kubernetes.io/name: upfdeployment diff --git a/controllers/amf/reconciler.go b/controllers/nf/amf/reconciler.go similarity index 86% rename from controllers/amf/reconciler.go rename to controllers/nf/amf/reconciler.go index 01194f8..7b92951 100644 --- a/controllers/amf/reconciler.go +++ b/controllers/nf/amf/reconciler.go @@ -40,24 +40,6 @@ type AMFDeploymentReconciler struct { Scheme *runtime.Scheme } -// Sets up the controller with the Manager -func (r *AMFDeploymentReconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(new(nephiov1alpha1.AMFDeployment)). - Owns(new(appsv1.Deployment)). - Owns(new(apiv1.ConfigMap)). - Complete(r) -} - -// +kubebuilder:rbac:groups=workload.nephio.org,resources=amfdeployments,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=workload.nephio.org,resources=amfdeployments/status,verbs=get;update;patch -// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=apps,resources=deployments/status,verbs=get -// +kubebuilder:rbac:groups="",resources=pods,verbs=get;list;watch -// +kubebuilder:rbac:groups="",resources=configmaps;services,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch -// +kubebuilder:rbac:groups="k8s.cni.cncf.io",resources=network-attachment-definitions,verbs=get;list;watch - // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. // TODO(user): Modify the Reconcile function to compare the state specified by @@ -70,7 +52,7 @@ func (r *AMFDeploymentReconciler) SetupWithManager(mgr ctrl.Manager) error { func (r *AMFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := log.FromContext(ctx).WithValues("AMFDeployment", req.NamespacedName) - amfDeployment := new(nephiov1alpha1.AMFDeployment) + amfDeployment := new(nephiov1alpha1.NFDeployment) err := r.Client.Get(ctx, req.NamespacedName, amfDeployment) if err != nil { if k8serrors.IsNotFound(err) { @@ -197,10 +179,11 @@ func (r *AMFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques return reconcile.Result{}, nil } -func (r *AMFDeploymentReconciler) syncStatus(ctx context.Context, deployment *appsv1.Deployment, amfDeployment *nephiov1alpha1.AMFDeployment) error { +func (r *AMFDeploymentReconciler) syncStatus(ctx context.Context, deployment *appsv1.Deployment, amfDeployment *nephiov1alpha1.NFDeployment) error { if nfDeploymentStatus, update := createNfDeploymentStatus(deployment, amfDeployment); update { amfDeployment = amfDeployment.DeepCopy() - amfDeployment.Status.NFDeploymentStatus = nfDeploymentStatus + //amfDeployment.Status.NFDeploymentStatus = nfDeploymentStatus + amfDeployment.Status = nfDeploymentStatus return r.Status().Update(ctx, amfDeployment) } else { return nil diff --git a/controllers/amf/resources.go b/controllers/nf/amf/resources.go similarity index 83% rename from controllers/amf/resources.go rename to controllers/nf/amf/resources.go index 96e7346..6a84f60 100644 --- a/controllers/amf/resources.go +++ b/controllers/nf/amf/resources.go @@ -27,17 +27,17 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" ) -func createDeployment(log logr.Logger, configMapVersion string, amfDeployment *nephiov1alpha1.AMFDeployment) (*appsv1.Deployment, error) { - namespace := amfDeployment.Namespace - instanceName := amfDeployment.Name - spec := amfDeployment.Spec +func createDeployment(log logr.Logger, configMapVersion string, nfDeployment *nephiov1alpha1.NFDeployment) (*appsv1.Deployment, error) { + namespace := nfDeployment.Namespace + instanceName := nfDeployment.Name + spec := nfDeployment.Spec replicas, resourceRequirements, err := createResourceRequirements(spec) if err != nil { return nil, err } - networkAttachmentDefinitionNetworks, err := createNetworkAttachmentDefinitionNetworks(amfDeployment.Name, &spec) + networkAttachmentDefinitionNetworks, err := createNetworkAttachmentDefinitionNetworks(nfDeployment.Name, &spec) if err != nil { return nil, err } @@ -132,9 +132,9 @@ func createDeployment(log logr.Logger, configMapVersion string, amfDeployment *n return deployment, nil } -func createService(amfDeployment *nephiov1alpha1.AMFDeployment) *apiv1.Service { - namespace := amfDeployment.Namespace - instanceName := amfDeployment.Name +func createService(nfDeployment *nephiov1alpha1.NFDeployment) *apiv1.Service { + namespace := nfDeployment.Namespace + instanceName := nfDeployment.Name labels := map[string]string{ "name": instanceName, @@ -160,13 +160,13 @@ func createService(amfDeployment *nephiov1alpha1.AMFDeployment) *apiv1.Service { return service } -func createConfigMap(log logr.Logger, amfDeployment *nephiov1alpha1.AMFDeployment) (*apiv1.ConfigMap, error) { - namespace := amfDeployment.Namespace - instanceName := amfDeployment.Name +func createConfigMap(log logr.Logger, nfDeployment *nephiov1alpha1.NFDeployment) (*apiv1.ConfigMap, error) { + namespace := nfDeployment.Namespace + instanceName := nfDeployment.Name - n2ip, err := controllers.GetFirstInterfaceConfigIPv4(amfDeployment.Spec.Interfaces, "n2") + n2ip, err := controllers.GetFirstInterfaceConfigIPv4(nfDeployment.Spec.Interfaces, "n2") if err != nil { - log.Error(err, "Interface N2 not found in AMFDeployment Spec") + log.Error(err, "Interface N2 not found in NFDeployment Spec") return nil, err } @@ -177,7 +177,7 @@ func createConfigMap(log logr.Logger, amfDeployment *nephiov1alpha1.AMFDeploymen configuration, err := renderConfigurationTemplate(templateValues) if err != nil { - log.Error(err, "Could not render AMF configuration template.") + log.Error(err, "Could not render NF configuration template.") return nil, err } @@ -199,7 +199,7 @@ func createConfigMap(log logr.Logger, amfDeployment *nephiov1alpha1.AMFDeploymen return configMap, nil } -func createResourceRequirements(amfDeploymentSpec nephiov1alpha1.AMFDeploymentSpec) (int32, *apiv1.ResourceRequirements, error) { +func createResourceRequirements(nfDeploymentSpec nephiov1alpha1.NFDeploymentSpec) (int32, *apiv1.ResourceRequirements, error) { // TODO: Requirements should be calculated based on DL, UL // TODO: increase number of recpicas based on NFDeployment.Capacity.MaxSessions @@ -211,7 +211,7 @@ func createResourceRequirements(amfDeploymentSpec nephiov1alpha1.AMFDeploymentSp var memoryLimit string var memoryRequest string - if amfDeploymentSpec.Capacity.MaxSubscribers > 1000 { + if nfDeploymentSpec.Capacity.MaxSubscribers > 1000 { cpuLimit = "300m" memoryLimit = "256Mi" cpuRequest = "300m" @@ -237,8 +237,8 @@ func createResourceRequirements(amfDeploymentSpec nephiov1alpha1.AMFDeploymentSp return replicas, &resources, nil } -func createNetworkAttachmentDefinitionNetworks(templateName string, amfDeploymentSpec *nephiov1alpha1.AMFDeploymentSpec) (string, error) { +func createNetworkAttachmentDefinitionNetworks(templateName string, nfDeploymentSpec *nephiov1alpha1.NFDeploymentSpec) (string, error) { return controllers.CreateNetworkAttachmentDefinitionNetworks(templateName, map[string][]nephiov1alpha1.InterfaceConfig{ - "n2": controllers.GetInterfaceConfigs(amfDeploymentSpec.Interfaces, "n2"), + "n2": controllers.GetInterfaceConfigs(nfDeploymentSpec.Interfaces, "n2"), }) } diff --git a/controllers/amf/resources_test.go b/controllers/nf/amf/resources_test.go similarity index 82% rename from controllers/amf/resources_test.go rename to controllers/nf/amf/resources_test.go index ecedb56..3ca5a9b 100644 --- a/controllers/amf/resources_test.go +++ b/controllers/nf/amf/resources_test.go @@ -33,8 +33,8 @@ import ( func TestCreateDeployment(t *testing.T) { log := log.FromContext(context.TODO()) - amfDeployment := newAmfDeployment("test-amf-deployment") - got, err := createDeployment(log, "111111", amfDeployment) + nfDeployment := newAmfDeployment("test-amf-deployment") + got, err := createDeployment(log, "111111", nfDeployment) if err != nil { t.Errorf("createDeployment() returned unexpected error %s", err.Error()) } @@ -142,19 +142,19 @@ func TestCreateDeployment(t *testing.T) { }, } if !reflect.DeepEqual(got, want) { - t.Errorf("createDeployment(%v) returned %v, want %v", amfDeployment, got, want) + t.Errorf("createDeployment(%v) returned %v, want %v", nfDeployment, got, want) } } func TestCreateConfigMap(t *testing.T) { log := log.FromContext(context.TODO()) - amfDeployment := newAmfDeployment("test-amf-deployment") - got, err := createConfigMap(log, amfDeployment) + nfDeployment := newAmfDeployment("test-amf-deployment") + got, err := createConfigMap(log, nfDeployment) if err != nil { t.Errorf("createConfigMap() returned unexpected error %v", err) } - n2ip, _ := controllers.GetFirstInterfaceConfigIPv4(amfDeployment.Spec.Interfaces, "n2") + n2ip, _ := controllers.GetFirstInterfaceConfigIPv4(nfDeployment.Spec.Interfaces, "n2") templateValues := configurationTemplateValues{ SVC_NAME: "test-amf-deployment", @@ -172,8 +172,8 @@ func TestCreateConfigMap(t *testing.T) { APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ - Name: amfDeployment.Name, - Namespace: amfDeployment.Namespace, + Name: nfDeployment.Name, + Namespace: nfDeployment.Namespace, }, Data: map[string]string{ "amfcfg.yaml": configuration, @@ -181,14 +181,14 @@ func TestCreateConfigMap(t *testing.T) { }, } if !reflect.DeepEqual(got, want) { - t.Errorf("createConfigMap(%v) returned %v, want %v", amfDeployment, got, want) + t.Errorf("createConfigMap(%v) returned %v, want %v", nfDeployment, got, want) } } func TestCreateResourceRequirements(t *testing.T) { - amfDeployment := newAmfDeployment("test-amf-deployment") + nfDeployment := newAmfDeployment("test-amf-deployment") - replicas, got, err := createResourceRequirements(amfDeployment.Spec) + replicas, got, err := createResourceRequirements(nfDeployment.Spec) if err != nil { t.Errorf("createResourceRequirements() returned unexpected error %v", err) } @@ -206,7 +206,7 @@ func TestCreateResourceRequirements(t *testing.T) { }, } if !reflect.DeepEqual(got, want) { - t.Errorf("createResourceRequirements(%v) returned %v, want %v", amfDeployment.Spec, got, want) + t.Errorf("createResourceRequirements(%v) returned %v, want %v", nfDeployment.Spec, got, want) } } @@ -225,8 +225,8 @@ func TestCreateNetworkAttachmentDefinitionName(t *testing.T) { } func TestCreateNetworkAttachmentDefinitionNetworks(t *testing.T) { - amfDeployment := newAmfDeployment("test-amf-deployment") - got, _ := createNetworkAttachmentDefinitionNetworks("test-amf-deployment", &amfDeployment.DeepCopy().Spec) + nfDeployment := newAmfDeployment("test-amf-deployment") + got, _ := createNetworkAttachmentDefinitionNetworks("test-amf-deployment", &nfDeployment.DeepCopy().Spec) want := `[ { @@ -238,33 +238,31 @@ func TestCreateNetworkAttachmentDefinitionNetworks(t *testing.T) { ]` if got != want { - t.Errorf("createNetworkAttachmentDefinitionNetworks(%v) returned %v, want %v", amfDeployment.Spec, got, want) + t.Errorf("createNetworkAttachmentDefinitionNetworks(%v) returned %v, want %v", nfDeployment.Spec, got, want) } } -func newAmfDeployment(name string) *nephiov1alpha1.AMFDeployment { +func newAmfDeployment(name string) *nephiov1alpha1.NFDeployment { interfaces := []nephiov1alpha1.InterfaceConfig{} n2interface := newAmfNxInterface("n2") interfaces = append(interfaces, n2interface) //dnnName := "apn-test" - return &nephiov1alpha1.AMFDeployment{ + return &nephiov1alpha1.NFDeployment{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: name + "-ns", }, - Spec: nephiov1alpha1.AMFDeploymentSpec{ - NFDeploymentSpec: nephiov1alpha1.NFDeploymentSpec{ - ConfigRefs: []apiv1.ObjectReference{}, - Capacity: &nephioreqv1alpha1.CapacitySpec{ - MaxUplinkThroughput: resource.MustParse("1G"), - MaxDownlinkThroughput: resource.MustParse("5G"), - MaxSessions: 1000, - MaxSubscribers: 1000, - MaxNFConnections: 2000, - }, - Interfaces: interfaces, + Spec: nephiov1alpha1.NFDeploymentSpec{ + ParametersRefs: []nephiov1alpha1.ObjectReference{}, + Capacity: &nephioreqv1alpha1.CapacitySpec{ + MaxUplinkThroughput: resource.MustParse("1G"), + MaxDownlinkThroughput: resource.MustParse("5G"), + MaxSessions: 1000, + MaxSubscribers: 1000, + MaxNFConnections: 2000, }, + Interfaces: interfaces, }, } } diff --git a/controllers/amf/status.go b/controllers/nf/amf/status.go similarity index 71% rename from controllers/amf/status.go rename to controllers/nf/amf/status.go index b1278bd..5687d21 100644 --- a/controllers/amf/status.go +++ b/controllers/nf/amf/status.go @@ -22,38 +22,38 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func createNfDeploymentStatus(deployment *appsv1.Deployment, amfDeployment *nephiov1alpha1.AMFDeployment) (nephiov1alpha1.NFDeploymentStatus, bool) { +func createNfDeploymentStatus(deployment *appsv1.Deployment, nfDeployment *nephiov1alpha1.NFDeployment) (nephiov1alpha1.NFDeploymentStatus, bool) { nfDeploymentStatus := nephiov1alpha1.NFDeploymentStatus{ ObservedGeneration: int32(deployment.Generation), - Conditions: amfDeployment.Status.Conditions, + Conditions: nfDeployment.Status.Conditions, } - // Return initial status if there are no status update happened for the AMFdeployment - if len(amfDeployment.Status.Conditions) == 0 { + // Return initial status if there are no status update happened for the NFdeployment + if len(nfDeployment.Status.Conditions) == 0 { nfDeploymentStatus.Conditions = append(nfDeploymentStatus.Conditions, metav1.Condition{ Type: string(nephiov1alpha1.Reconciling), Status: metav1.ConditionFalse, Reason: "MinimumReplicasNotAvailable", - Message: "AMFDeployment pod(s) is(are) starting.", + Message: "NFDeployment pod(s) is(are) starting.", LastTransitionTime: metav1.Now(), }) return nfDeploymentStatus, true - } else if (len(deployment.Status.Conditions) == 0) && (len(amfDeployment.Status.Conditions) > 0) { + } else if (len(deployment.Status.Conditions) == 0) && (len(nfDeployment.Status.Conditions) > 0) { return nfDeploymentStatus, false } // Check the last underlying Deployment status and deduce condition from it lastDeploymentCondition := deployment.Status.Conditions[0] - lastAmfDeploymentCondition := amfDeployment.Status.Conditions[len(amfDeployment.Status.Conditions)-1] + lastNfDeploymentCondition := nfDeployment.Status.Conditions[len(nfDeployment.Status.Conditions)-1] - // Deployemnt and AMFDeployment have different names for processing state, hence we check if one is processing another is reconciling, then state is equal - if (lastDeploymentCondition.Type == appsv1.DeploymentProgressing) && (lastAmfDeploymentCondition.Type == string(nephiov1alpha1.Reconciling)) { + // Deployemnt and NFDeployment have different names for processing state, hence we check if one is processing another is reconciling, then state is equal + if (lastDeploymentCondition.Type == appsv1.DeploymentProgressing) && (lastNfDeploymentCondition.Type == string(nephiov1alpha1.Reconciling)) { return nfDeploymentStatus, false } // if both status types are Available, don't update. - if string(lastDeploymentCondition.Type) == string(lastAmfDeploymentCondition.Type) { + if string(lastDeploymentCondition.Type) == string(lastNfDeploymentCondition.Type) { return nfDeploymentStatus, false } @@ -63,7 +63,7 @@ func createNfDeploymentStatus(deployment *appsv1.Deployment, amfDeployment *neph Type: string(nephiov1alpha1.Available), Status: metav1.ConditionTrue, Reason: "MinimumReplicasAvailable", - Message: "AMFDeployment pods are available.", + Message: "NFDeployment pods are available.", LastTransitionTime: metav1.Now(), }) @@ -72,7 +72,7 @@ func createNfDeploymentStatus(deployment *appsv1.Deployment, amfDeployment *neph Type: string(nephiov1alpha1.Reconciling), Status: metav1.ConditionFalse, Reason: "MinimumReplicasNotAvailable", - Message: "AMFDeployment pod(s) is(are) starting.", + Message: "NFDeployment pod(s) is(are) starting.", LastTransitionTime: metav1.Now(), }) @@ -81,10 +81,9 @@ func createNfDeploymentStatus(deployment *appsv1.Deployment, amfDeployment *neph Type: string(nephiov1alpha1.Stalled), Status: metav1.ConditionFalse, Reason: "MinimumReplicasNotAvailable", - Message: "AMFDeployment pod(s) is(are) failing.", + Message: "NFDeployment pod(s) is(are) failing.", LastTransitionTime: metav1.Now(), }) } - return nfDeploymentStatus, true } diff --git a/controllers/amf/status_test.go b/controllers/nf/amf/status_test.go similarity index 69% rename from controllers/amf/status_test.go rename to controllers/nf/amf/status_test.go index 1dea379..2bebee3 100644 --- a/controllers/amf/status_test.go +++ b/controllers/nf/amf/status_test.go @@ -26,128 +26,128 @@ import ( ) func TestCreateNfDeploymentStatusFirst(t *testing.T) { - amfDeployment := newAmfDeployment("test-amf-deployment") + nfDeployment := newAmfDeployment("test-amf-deployment") deployment := new(appsv1.Deployment) want := nephiov1alpha1.NFDeploymentStatus{ ObservedGeneration: int32(deployment.Generation), - Conditions: amfDeployment.Status.Conditions, + Conditions: nfDeployment.Status.Conditions, } var condition metav1.Condition condition.Type = string(nephiov1alpha1.Reconciling) condition.Status = metav1.ConditionFalse condition.Reason = "MinimumReplicasNotAvailable" - condition.Message = "AMFDeployment pod(s) is(are) starting." + condition.Message = "NFDeployment pod(s) is(are) starting." want.Conditions = append(want.Conditions, condition) - got, b := createNfDeploymentStatus(deployment, amfDeployment) + got, b := createNfDeploymentStatus(deployment, nfDeployment) gotCondition := got.Conditions[0] gotCondition.LastTransitionTime = metav1.Time{} if !reflect.DeepEqual(gotCondition, condition) { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, amfDeployment, got, want) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, got, want) } if !b { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, amfDeployment, b, true) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, b, true) } } func TestCreateNfDeploymentStatusDeploymentNotReady(t *testing.T) { - amfDeployment := newAmfDeployment("test-amf-deployment") + nfDeployment := newAmfDeployment("test-amf-deployment") deployment := new(appsv1.Deployment) var condition metav1.Condition condition.Type = string(nephiov1alpha1.Reconciling) condition.Status = metav1.ConditionFalse condition.Reason = "MinimumReplicasNotAvailable" - condition.Message = "AMFDeployment pod(s) is(are) starting." + condition.Message = "NFDeployment pod(s) is(are) starting." condition.LastTransitionTime = metav1.Now() - amfDeployment.Status.Conditions = append(amfDeployment.Status.Conditions, condition) + nfDeployment.Status.Conditions = append(nfDeployment.Status.Conditions, condition) - want := amfDeployment.Status.NFDeploymentStatus + want := nfDeployment.Status - got, b := createNfDeploymentStatus(deployment, amfDeployment) + got, b := createNfDeploymentStatus(deployment, nfDeployment) if !reflect.DeepEqual(got, want) { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, amfDeployment, got, want) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, got, want) } if b { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, amfDeployment, b, false) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, b, false) } } func TestCreateNfDeploymentStatusProcessing(t *testing.T) { - amfDeployment := newAmfDeployment("test-amf-deployment") + nfDeployment := newAmfDeployment("test-amf-deployment") deployment := new(appsv1.Deployment) var condition metav1.Condition condition.Type = string(nephiov1alpha1.Reconciling) deploymentCondition := &appsv1.DeploymentCondition{} deploymentCondition.Type = appsv1.DeploymentProgressing - amfDeployment.Status.Conditions = append(amfDeployment.Status.Conditions, condition) + nfDeployment.Status.Conditions = append(nfDeployment.Status.Conditions, condition) deployment.Status.Conditions = append(deployment.Status.Conditions, *deploymentCondition) - want := amfDeployment.Status.NFDeploymentStatus + want := nfDeployment.Status - got, b := createNfDeploymentStatus(deployment, amfDeployment) + got, b := createNfDeploymentStatus(deployment, nfDeployment) if !reflect.DeepEqual(got, want) { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, amfDeployment, got, want) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, got, want) } if b { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, amfDeployment, b, false) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, b, false) } } func TestCreateNfDeploymentStatusAvailable(t *testing.T) { - amfDeployment := newAmfDeployment("test-amf-deployment") + nfDeployment := newAmfDeployment("test-amf-deployment") deployment := new(appsv1.Deployment) var condition metav1.Condition condition.Type = string(nephiov1alpha1.Available) deploymentCondition := &appsv1.DeploymentCondition{} deploymentCondition.Type = appsv1.DeploymentAvailable - amfDeployment.Status.Conditions = append(amfDeployment.Status.Conditions, condition) + nfDeployment.Status.Conditions = append(nfDeployment.Status.Conditions, condition) deployment.Status.Conditions = append(deployment.Status.Conditions, *deploymentCondition) - want := amfDeployment.Status.NFDeploymentStatus + want := nfDeployment.Status - got, b := createNfDeploymentStatus(deployment, amfDeployment) + got, b := createNfDeploymentStatus(deployment, nfDeployment) if !reflect.DeepEqual(got, want) { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, amfDeployment, got, want) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, got, want) } if b { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, amfDeployment, b, false) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, b, false) } } func TestCreateNfDeploymentStatusDeploymentAvailable(t *testing.T) { - amfDeployment := newAmfDeployment("test-amf-deployment") + nfDeployment := newAmfDeployment("test-amf-deployment") deployment := new(appsv1.Deployment) var condition metav1.Condition condition.Type = string(nephiov1alpha1.Reconciling) condition.Status = metav1.ConditionFalse condition.Reason = "MinimumReplicasNotAvailable" - condition.Message = "AMFDeployment pod(s) is(are) starting." + condition.Message = "NFDeployment pod(s) is(are) starting." deploymentCondition := &appsv1.DeploymentCondition{} deploymentCondition.Type = appsv1.DeploymentAvailable deploymentCondition.Reason = "MinimumReplicasAvailable" - amfDeployment.Status.Conditions = append(amfDeployment.Status.Conditions, condition) + nfDeployment.Status.Conditions = append(nfDeployment.Status.Conditions, condition) deployment.Status.Conditions = append(deployment.Status.Conditions, *deploymentCondition) - want := amfDeployment.Status.NFDeploymentStatus + want := nfDeployment.Status condition.Type = string(nephiov1alpha1.Available) condition.Status = metav1.ConditionTrue condition.Reason = "MinimumReplicasAvailable" - condition.Message = "AMFDeployment pods are available." + condition.Message = "NFDeployment pods are available." want.Conditions = append(want.Conditions, condition) - got, b := createNfDeploymentStatus(deployment, amfDeployment) + got, b := createNfDeploymentStatus(deployment, nfDeployment) gotCondition := got.Conditions[1] gotCondition.LastTransitionTime = metav1.Time{} @@ -155,35 +155,35 @@ func TestCreateNfDeploymentStatusDeploymentAvailable(t *testing.T) { got.Conditions = append(got.Conditions, gotCondition) if !reflect.DeepEqual(got, want) { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, amfDeployment, got, want) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, got, want) } if !b { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, amfDeployment, b, true) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, b, true) } } func TestCreateNfDeploymentStatusDeploymentProcessing(t *testing.T) { - amfDeployment := newAmfDeployment("test-amf-deployment") + nfDeployment := newAmfDeployment("test-amf-deployment") deployment := new(appsv1.Deployment) var condition metav1.Condition condition.Type = string(nephiov1alpha1.Available) condition.Status = metav1.ConditionTrue condition.Reason = "MinimumReplicasAvailable" - condition.Message = "AMFDeployment pods are available" + condition.Message = "NFDeployment pods are available" deploymentCondition := &appsv1.DeploymentCondition{} deploymentCondition.Type = appsv1.DeploymentProgressing - amfDeployment.Status.Conditions = append(amfDeployment.Status.Conditions, condition) + nfDeployment.Status.Conditions = append(nfDeployment.Status.Conditions, condition) deployment.Status.Conditions = append(deployment.Status.Conditions, *deploymentCondition) - want := amfDeployment.Status.NFDeploymentStatus + want := nfDeployment.Status condition.Type = string(nephiov1alpha1.Reconciling) condition.Status = metav1.ConditionFalse condition.Reason = "MinimumReplicasNotAvailable" - condition.Message = "AMFDeployment pod(s) is(are) starting." + condition.Message = "NFDeployment pod(s) is(are) starting." want.Conditions = append(want.Conditions, condition) - got, b := createNfDeploymentStatus(deployment, amfDeployment) + got, b := createNfDeploymentStatus(deployment, nfDeployment) gotCondition := got.Conditions[1] gotCondition.LastTransitionTime = metav1.Time{} @@ -191,35 +191,35 @@ func TestCreateNfDeploymentStatusDeploymentProcessing(t *testing.T) { got.Conditions = append(got.Conditions, gotCondition) if !reflect.DeepEqual(got, want) { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, amfDeployment, got, want) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, got, want) } if !b { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, amfDeployment, b, true) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, b, true) } } func TestCreateNfDeploymentStatusReplicaFailure(t *testing.T) { - amfDeployment := newAmfDeployment("test-amf-deployment") + nfDeployment := newAmfDeployment("test-amf-deployment") deployment := new(appsv1.Deployment) var condition metav1.Condition condition.Type = string(nephiov1alpha1.Available) condition.Status = metav1.ConditionTrue condition.Reason = "MinimumReplicasAvailable" - condition.Message = "AMFDeployment pods are available" + condition.Message = "NFDeployment pods are available" deploymentCondition := &appsv1.DeploymentCondition{} deploymentCondition.Type = appsv1.DeploymentReplicaFailure - amfDeployment.Status.Conditions = append(amfDeployment.Status.Conditions, condition) + nfDeployment.Status.Conditions = append(nfDeployment.Status.Conditions, condition) deployment.Status.Conditions = append(deployment.Status.Conditions, *deploymentCondition) - want := amfDeployment.Status.NFDeploymentStatus + want := nfDeployment.Status condition.Type = string(nephiov1alpha1.Stalled) condition.Status = metav1.ConditionFalse condition.Reason = "MinimumReplicasNotAvailable" - condition.Message = "AMFDeployment pod(s) is(are) failing." + condition.Message = "NFDeployment pod(s) is(are) failing." want.Conditions = append(want.Conditions, condition) - got, b := createNfDeploymentStatus(deployment, amfDeployment) + got, b := createNfDeploymentStatus(deployment, nfDeployment) gotCondition := got.Conditions[1] gotCondition.LastTransitionTime = metav1.Time{} @@ -227,9 +227,9 @@ func TestCreateNfDeploymentStatusReplicaFailure(t *testing.T) { got.Conditions = append(got.Conditions, gotCondition) if !reflect.DeepEqual(got, want) { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, amfDeployment, got, want) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, got, want) } if !b { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, amfDeployment, b, true) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, b, true) } } diff --git a/controllers/amf/templates.go b/controllers/nf/amf/templates.go similarity index 100% rename from controllers/amf/templates.go rename to controllers/nf/amf/templates.go diff --git a/controllers/nf/reconciler.go b/controllers/nf/reconciler.go new file mode 100644 index 0000000..6595215 --- /dev/null +++ b/controllers/nf/reconciler.go @@ -0,0 +1,109 @@ +/* +Copyright 2023 The Nephio Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package nf + +import ( + "context" + + nephiov1alpha1 "github.com/nephio-project/api/nf_deployments/v1alpha1" + amf "github.com/nephio-project/free5gc/controllers/nf/amf" + smf "github.com/nephio-project/free5gc/controllers/nf/smf" + upf "github.com/nephio-project/free5gc/controllers/nf/upf" + appsv1 "k8s.io/api/apps/v1" + apiv1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/reconcile" +) + +// Reconciles a NFDeployment resource +type NFDeploymentReconciler struct { + client.Client + Scheme *runtime.Scheme +} + +// Sets up the controller with the Manager +func (r *NFDeploymentReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(new(nephiov1alpha1.NFDeployment)). + Owns(new(appsv1.Deployment)). + Owns(new(apiv1.ConfigMap)). + Complete(r) +} + +// +kubebuilder:rbac:groups=workload.nephio.org,resources=nfdeployments,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=workload.nephio.org,resources=nfdeployments/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=apps,resources=deployments/status,verbs=get +// +kubebuilder:rbac:groups="",resources=pods,verbs=get;list;watch +// +kubebuilder:rbac:groups="",resources=configmaps;services,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch +// +kubebuilder:rbac:groups="k8s.cni.cncf.io",resources=network-attachment-definitions,verbs=get;list;watch + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the NFDeployment object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.1/pkg/reconcile +func (r *NFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + log := log.FromContext(ctx).WithValues("NFDeployment", req.NamespacedName) + + nfDeployment := new(nephiov1alpha1.NFDeployment) + err := r.Client.Get(ctx, req.NamespacedName, nfDeployment) + if err != nil { + if k8serrors.IsNotFound(err) { + log.Info("NFDeployment resource not found, ignoring because object must be deleted") + return reconcile.Result{}, nil + } + log.Error(err, "Failed to get NFDeployment") + return reconcile.Result{}, err + } + + upfReconciler := &upf.UPFDeploymentReconciler{ + Client: r.Client, + Scheme: r.Scheme, + } + amfReconciler := &amf.AMFDeploymentReconciler{ + Client: r.Client, + Scheme: r.Scheme, + } + smfReconciler := &smf.SMFDeploymentReconciler{ + Client: r.Client, + Scheme: r.Scheme, + } + + switch nfDeployment.Spec.Provider { + case "upf.free5gc.nephio.org": + upfresult, _ := upfReconciler.Reconcile(ctx, req) + return upfresult, nil + case "smf.free5gc.nephio.org": + smfresult, _ := smfReconciler.Reconcile(ctx, req) + return smfresult, nil + case "amf.free5gc.nephio.org": + amfresult, _ := amfReconciler.Reconcile(ctx, req) + return amfresult, nil + default: + return reconcile.Result{}, nil + } +} diff --git a/controllers/smf/reconciler.go b/controllers/nf/smf/reconciler.go similarity index 80% rename from controllers/smf/reconciler.go rename to controllers/nf/smf/reconciler.go index 63b2d89..d03a284 100644 --- a/controllers/smf/reconciler.go +++ b/controllers/nf/smf/reconciler.go @@ -23,6 +23,7 @@ import ( nephiov1alpha1 "github.com/nephio-project/api/nf_deployments/v1alpha1" refv1alpha1 "github.com/nephio-project/api/references/v1alpha1" "github.com/nephio-project/free5gc/controllers" + appsv1 "k8s.io/api/apps/v1" apiv1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" @@ -40,21 +41,12 @@ type SMFDeploymentReconciler struct { Scheme *runtime.Scheme } -// Sets up the controller with the Manager -func (r *SMFDeploymentReconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(new(nephiov1alpha1.SMFDeployment)). - Owns(new(appsv1.Deployment)). - Owns(new(apiv1.ConfigMap)). - Complete(r) -} - // Fetch all SMF ConfigRefs -func (r *SMFDeploymentReconciler) GetAllConfigRefs(ctx context.Context, smfDeployment *nephiov1alpha1.SMFDeployment) ([]*refv1alpha1.Config, error) { +func (r *SMFDeploymentReconciler) GetAllConfigRefs(ctx context.Context, smfDeployment *nephiov1alpha1.NFDeployment, namespace types.NamespacedName) ([]*refv1alpha1.Config, error) { var ret []*refv1alpha1.Config - for _, objRef := range smfDeployment.Spec.ConfigRefs { + for _, objRef := range smfDeployment.Spec.ParametersRefs { cfgRef := &refv1alpha1.Config{} - if err := r.Client.Get(ctx, types.NamespacedName{Name: objRef.Name, Namespace: objRef.Namespace}, cfgRef); err != nil { + if err := r.Client.Get(ctx, types.NamespacedName{Name: *objRef.Name, Namespace: namespace.Namespace}, cfgRef); err != nil { return ret, err } ret = append(ret, cfgRef) @@ -62,15 +54,6 @@ func (r *SMFDeploymentReconciler) GetAllConfigRefs(ctx context.Context, smfDeplo return ret, nil } -// +kubebuilder:rbac:groups=workload.nephio.org,resources=smfdeployments,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=workload.nephio.org,resources=smfdeployments/status,verbs=get;update;patch -// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=apps,resources=deployments/status,verbs=get -// +kubebuilder:rbac:groups="",resources=pods,verbs=get;list;watch -// +kubebuilder:rbac:groups="",resources=configmaps;services,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch -// +kubebuilder:rbac:groups="k8s.cni.cncf.io",resources=network-attachment-definitions,verbs=get;list;watch - // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. // TODO(user): Modify the Reconcile function to compare the state specified by @@ -83,7 +66,7 @@ func (r *SMFDeploymentReconciler) GetAllConfigRefs(ctx context.Context, smfDeplo func (r *SMFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := log.FromContext(ctx).WithValues("SMFDeployment", req.NamespacedName) - smfDeployment := new(nephiov1alpha1.SMFDeployment) + smfDeployment := new(nephiov1alpha1.NFDeployment) err := r.Client.Get(ctx, req.NamespacedName, smfDeployment) if err != nil { if k8serrors.IsNotFound(err) { @@ -93,7 +76,6 @@ func (r *SMFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques log.Error(err, "Failed to get SMFDeployment") return reconcile.Result{}, err } - namespace := smfDeployment.Namespace configMapFound := false @@ -111,7 +93,6 @@ func (r *SMFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques if err := r.Client.Get(ctx, types.NamespacedName{Name: serviceName, Namespace: namespace}, currentService); err == nil { serviceFound = true } - deploymentFound := false deploymentName := smfDeployment.Name currentDeployment := new(appsv1.Deployment) @@ -132,16 +113,18 @@ func (r *SMFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques if currentDeployment.Spec.Template.Annotations[controllers.ConfigMapVersionAnnotation] != configMapVersion { log.Info("ConfigMap has been updated, rolling Deployment pods", "Deployment.namespace", currentDeployment.Namespace, "Deployment.name", currentDeployment.Name) currentDeployment.Spec.Template.Annotations[controllers.ConfigMapVersionAnnotation] = configMapVersion + if err := r.Update(ctx, currentDeployment); err != nil { log.Error(err, "Failed to update Deployment", "Deployment.namespace", currentDeployment.Namespace, "Deployment.name", currentDeployment.Name) return reconcile.Result{}, err } + return reconcile.Result{Requeue: true}, nil } } var smfConfigRefs []*refv1alpha1.Config - if smfConfigRefs, err = r.GetAllConfigRefs(ctx, smfDeployment); err != nil { + if smfConfigRefs, err = r.GetAllConfigRefs(ctx, smfDeployment, req.NamespacedName); err != nil { log.Info("Not all config references found... rerun reconcile") return reconcile.Result{}, err } @@ -149,7 +132,6 @@ func (r *SMFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques if configMap, err := createConfigMap(log, smfDeployment, smfConfigRefs); err == nil { if !configMapFound { log.Info("Creating ConfigMap", "ConfigMap.namespace", configMap.Namespace, "ConfigMap.name", configMap.Name) - // Set the controller reference, specifying that SMFDeployment controls the underlying ConfigMap if err := ctrl.SetControllerReference(smfDeployment, configMap, r.Scheme); err != nil { log.Error(err, "Got error while setting Owner reference on ConfigMap", "ConfigMap.namespace", configMap.Namespace, "ConfigMap.name", configMap.Name) @@ -159,7 +141,6 @@ func (r *SMFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques log.Error(err, "Failed to create ConfigMap", "ConfigMap.namespace", configMap.Namespace, "ConfigMap.name", configMap.Name) return reconcile.Result{}, err } - configMapVersion = configMap.ResourceVersion } } else { @@ -204,12 +185,6 @@ func (r *SMFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques return reconcile.Result{RequeueAfter: time.Duration(10) * time.Second}, nil } } else { - /* - if err := ctrl.SetControllerReference(smfDeployment, deployment, r.Scheme); err != nil { - log.Error(err, "Got error while setting Owner reference during Deployment update", "Deployment.namespace", deployment.Name, "Deployment.name", deployment.Name) - } - log.Info("Updating Deployment", "Deployment.namespace", deployment.Name, "Deployment.name", deployment.Name) - */ if err = r.Client.Update(ctx, deployment); err != nil { log.Error(err, "Failed to update Deployment", "Deployment.namespace", deployment.Namespace, "Deployment.name", deployment.Name) @@ -223,10 +198,11 @@ func (r *SMFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques return reconcile.Result{}, nil } -func (r *SMFDeploymentReconciler) syncStatus(ctx context.Context, deployment *appsv1.Deployment, smfDeployment *nephiov1alpha1.SMFDeployment) error { +func (r *SMFDeploymentReconciler) syncStatus(ctx context.Context, deployment *appsv1.Deployment, smfDeployment *nephiov1alpha1.NFDeployment) error { if nfDeploymentStatus, update := createNfDeploymentStatus(deployment, smfDeployment); update { smfDeployment = smfDeployment.DeepCopy() - smfDeployment.Status.NFDeploymentStatus = nfDeploymentStatus + //smfDeployment.Status.NFDeploymentStatus = nfDeploymentStatus + smfDeployment.Status = nfDeploymentStatus return r.Status().Update(ctx, smfDeployment) } else { return nil diff --git a/controllers/smf/resources.go b/controllers/nf/smf/resources.go similarity index 92% rename from controllers/smf/resources.go rename to controllers/nf/smf/resources.go index ee3b9d3..d0b6af9 100644 --- a/controllers/smf/resources.go +++ b/controllers/nf/smf/resources.go @@ -32,7 +32,7 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" ) -func createDeployment(log logr.Logger, configMapVersion string, smfDeployment *nephiov1alpha1.SMFDeployment) (*appsv1.Deployment, error) { +func createDeployment(log logr.Logger, configMapVersion string, smfDeployment *nephiov1alpha1.NFDeployment) (*appsv1.Deployment, error) { namespace := smfDeployment.Namespace instanceName := smfDeployment.Name spec := smfDeployment.Spec @@ -139,7 +139,7 @@ func createDeployment(log logr.Logger, configMapVersion string, smfDeployment *n return deployment, nil } -func createService(smfDeployment *nephiov1alpha1.SMFDeployment) *apiv1.Service { +func createService(smfDeployment *nephiov1alpha1.NFDeployment) *apiv1.Service { namespace := smfDeployment.Namespace instanceName := smfDeployment.Name @@ -167,7 +167,7 @@ func createService(smfDeployment *nephiov1alpha1.SMFDeployment) *apiv1.Service { return service } -func createConfigMap(log logr.Logger, smfDeployment *nephiov1alpha1.SMFDeployment, smfConfigRefs []*refv1alpha1.Config) (*apiv1.ConfigMap, error) { +func createConfigMap(log logr.Logger, smfDeployment *nephiov1alpha1.NFDeployment, smfConfigRefs []*refv1alpha1.Config) (*apiv1.ConfigMap, error) { namespace := smfDeployment.Namespace instanceName := smfDeployment.Name @@ -241,7 +241,7 @@ func createConfigMap(log logr.Logger, smfDeployment *nephiov1alpha1.SMFDeploymen return configMap, nil } -func createResourceRequirements(smfDeploymentSpec nephiov1alpha1.SMFDeploymentSpec) (int32, *apiv1.ResourceRequirements, error) { +func createResourceRequirements(smfDeploymentSpec nephiov1alpha1.NFDeploymentSpec) (int32, *apiv1.ResourceRequirements, error) { // TODO: Requirements should be calculated based on DL, UL // TODO: Increase number of recpicas based on NFDeployment.Capacity.MaxSessions @@ -277,13 +277,13 @@ func createResourceRequirements(smfDeploymentSpec nephiov1alpha1.SMFDeploymentSp return replicas, &resources, nil } -func createNetworkAttachmentDefinitionNetworks(templateName string, smfDeploymentSpec *nephiov1alpha1.SMFDeploymentSpec) (string, error) { +func createNetworkAttachmentDefinitionNetworks(templateName string, smfDeploymentSpec *nephiov1alpha1.NFDeploymentSpec) (string, error) { return controllers.CreateNetworkAttachmentDefinitionNetworks(templateName, map[string][]nephiov1alpha1.InterfaceConfig{ "n4": controllers.GetInterfaceConfigs(smfDeploymentSpec.Interfaces, "n4"), }) } -func getNetworkInstances(upfDeploymentSpec *nephiov1alpha1.UPFDeploymentSpec, interfaceName string) ([]nephiov1alpha1.NetworkInstance, bool) { +func getNetworkInstances(upfDeploymentSpec *nephiov1alpha1.NFDeploymentSpec, interfaceName string) ([]nephiov1alpha1.NetworkInstance, bool) { var networkInstances []nephiov1alpha1.NetworkInstance for _, networkInstance := range upfDeploymentSpec.NetworkInstances { @@ -301,14 +301,14 @@ func getNetworkInstances(upfDeploymentSpec *nephiov1alpha1.UPFDeploymentSpec, in } } -func extractConfigRefUPFDeployment(refs []*refv1alpha1.Config) ([]nephiov1alpha1.UPFDeployment, error) { - var ret []nephiov1alpha1.UPFDeployment +func extractConfigRefUPFDeployment(refs []*refv1alpha1.Config) ([]nephiov1alpha1.NFDeployment, error) { + var ret []nephiov1alpha1.NFDeployment for _, ref := range refs { var b []byte if ref.Spec.Config.Object == nil { b = ref.Spec.Config.Raw } else { - if ref.Spec.Config.Object.GetObjectKind().GroupVersionKind() == nephiov1alpha1.UPFDeploymentGroupVersionKind { + if ref.Spec.Config.Object.GetObjectKind().GroupVersionKind() == nephiov1alpha1.NFDeploymentGroupVersionKind { var err error if b, err = json.Marshal(ref.Spec.Config.Object); err != nil { return nil, err @@ -317,7 +317,7 @@ func extractConfigRefUPFDeployment(refs []*refv1alpha1.Config) ([]nephiov1alpha1 continue } } - upfDeployment := &nephiov1alpha1.UPFDeployment{} + upfDeployment := &nephiov1alpha1.NFDeployment{} if err := json.Unmarshal(b, upfDeployment); err != nil { return nil, err } else { diff --git a/controllers/smf/resources_test.go b/controllers/nf/smf/resources_test.go similarity index 89% rename from controllers/smf/resources_test.go rename to controllers/nf/smf/resources_test.go index 52d5bfc..a0cd941 100644 --- a/controllers/smf/resources_test.go +++ b/controllers/nf/smf/resources_test.go @@ -155,6 +155,7 @@ func TestCreateConfigMap(t *testing.T) { log := log.FromContext(context.TODO()) var refList []*refv1alpha1.Config smfDeployment := newSmfDeployment("test-smf-deployment") + // Need to comment from here /* ref := &refv1alpha1.ConfigRef{ ObjectMeta: metav1.ObjectMeta{ @@ -171,6 +172,7 @@ func TestCreateConfigMap(t *testing.T) { } refList = append(refList, ref) */ + //Need to comment till here interfaces := []nephiov1alpha1.InterfaceConfig{} upfN3Int := newSmfNxInterface("n3") upfN4Int := newSmfNxInterface("n4") @@ -179,42 +181,41 @@ func TestCreateConfigMap(t *testing.T) { interfaces = append(interfaces, upfN3Int) interfaces = append(interfaces, upfN4Int) dnnName := "apn-test" - upfDeploy := &nephiov1alpha1.UPFDeployment{ + upfDeploy := &nephiov1alpha1.NFDeployment{ TypeMeta: metav1.TypeMeta{ APIVersion: "workload.nephio.org/v1alpha1", - Kind: "UPFDeployment", + Kind: "NFDeployment", }, ObjectMeta: metav1.ObjectMeta{ Name: "free5gc-upf-1", Namespace: "test-smf-deployment", }, - Spec: nephiov1alpha1.UPFDeploymentSpec{ - NFDeploymentSpec: nephiov1alpha1.NFDeploymentSpec{ - ConfigRefs: []apiv1.ObjectReference{}, - Capacity: &nephioreqv1alpha1.CapacitySpec{ - MaxUplinkThroughput: resource.MustParse("1G"), - MaxDownlinkThroughput: resource.MustParse("5G"), - }, - Interfaces: interfaces, - NetworkInstances: []nephiov1alpha1.NetworkInstance{ - { - Name: "vpc-internet", - Interfaces: []string{ - "n6", - }, - DataNetworks: []nephiov1alpha1.DataNetwork{ - { - Name: &dnnName, - Pool: []nephiov1alpha1.Pool{ - { - Prefix: "100.100.0.0/16", - }, + Spec: nephiov1alpha1.NFDeploymentSpec{ + //NFDeploymentSpec: nephiov1alpha1.NFDeploymentSpec{ + ParametersRefs: []nephiov1alpha1.ObjectReference{}, + Capacity: &nephioreqv1alpha1.CapacitySpec{ + MaxUplinkThroughput: resource.MustParse("1G"), + MaxDownlinkThroughput: resource.MustParse("5G"), + }, + Interfaces: interfaces, + NetworkInstances: []nephiov1alpha1.NetworkInstance{ + { + Name: "vpc-internet", + Interfaces: []string{ + "n6", + }, + DataNetworks: []nephiov1alpha1.DataNetwork{ + { + Name: &dnnName, + Pool: []nephiov1alpha1.Pool{ + { + Prefix: "100.100.0.0/16", }, }, }, - BGP: nil, - Peers: []nephiov1alpha1.PeerConfig{}, }, + BGP: nil, + Peers: []nephiov1alpha1.PeerConfig{}, }, }, }, @@ -349,26 +350,25 @@ func TestCreateNetworkAttachmentDefinitionNetworks(t *testing.T) { } } -func newSmfDeployment(name string) *nephiov1alpha1.SMFDeployment { +func newSmfDeployment(name string) *nephiov1alpha1.NFDeployment { interfaces := []nephiov1alpha1.InterfaceConfig{} n4int := newSmfNxInterface("n4") interfaces = append(interfaces, n4int) - return &nephiov1alpha1.SMFDeployment{ + return &nephiov1alpha1.NFDeployment{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: name + "-ns", }, - Spec: nephiov1alpha1.SMFDeploymentSpec{ - NFDeploymentSpec: nephiov1alpha1.NFDeploymentSpec{ - ConfigRefs: []apiv1.ObjectReference{}, - Capacity: &nephioreqv1alpha1.CapacitySpec{ - MaxSessions: 1000, - MaxSubscribers: 1000, - MaxNFConnections: 2000, - }, - Interfaces: interfaces, + Spec: nephiov1alpha1.NFDeploymentSpec{ + //NFDeploymentSpec: nephiov1alpha1.NFDeploymentSpec{ + ParametersRefs: []nephiov1alpha1.ObjectReference{}, + Capacity: &nephioreqv1alpha1.CapacitySpec{ + MaxSessions: 1000, + MaxSubscribers: 1000, + MaxNFConnections: 2000, }, + Interfaces: interfaces, }, } } diff --git a/controllers/smf/status.go b/controllers/nf/smf/status.go similarity index 97% rename from controllers/smf/status.go rename to controllers/nf/smf/status.go index 46f3165..8a170f4 100644 --- a/controllers/smf/status.go +++ b/controllers/nf/smf/status.go @@ -22,7 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func createNfDeploymentStatus(deployment *appsv1.Deployment, smfDeployment *nephiov1alpha1.SMFDeployment) (nephiov1alpha1.NFDeploymentStatus, bool) { +func createNfDeploymentStatus(deployment *appsv1.Deployment, smfDeployment *nephiov1alpha1.NFDeployment) (nephiov1alpha1.NFDeploymentStatus, bool) { nfDeploymentStatus := nephiov1alpha1.NFDeploymentStatus{ ObservedGeneration: int32(deployment.Generation), Conditions: smfDeployment.Status.Conditions, diff --git a/controllers/smf/status_test.go b/controllers/nf/smf/status_test.go similarity index 96% rename from controllers/smf/status_test.go rename to controllers/nf/smf/status_test.go index 57929ba..72137a9 100644 --- a/controllers/smf/status_test.go +++ b/controllers/nf/smf/status_test.go @@ -67,7 +67,7 @@ func TestCreateNfDeploymentStatusDeploymentNotReady(t *testing.T) { condition.LastTransitionTime = metav1.Now() smfDeployment.Status.Conditions = append(smfDeployment.Status.Conditions, condition) - want := smfDeployment.Status.NFDeploymentStatus + want := smfDeployment.Status got, b := createNfDeploymentStatus(deployment, smfDeployment) @@ -90,7 +90,7 @@ func TestCreateNfDeploymentStatusProcessing(t *testing.T) { smfDeployment.Status.Conditions = append(smfDeployment.Status.Conditions, condition) deployment.Status.Conditions = append(deployment.Status.Conditions, *deploymentCondition) - want := smfDeployment.Status.NFDeploymentStatus + want := smfDeployment.Status got, b := createNfDeploymentStatus(deployment, smfDeployment) @@ -113,7 +113,7 @@ func TestCreateNfDeploymentStatusAvailable(t *testing.T) { smfDeployment.Status.Conditions = append(smfDeployment.Status.Conditions, condition) deployment.Status.Conditions = append(deployment.Status.Conditions, *deploymentCondition) - want := smfDeployment.Status.NFDeploymentStatus + want := smfDeployment.Status got, b := createNfDeploymentStatus(deployment, smfDeployment) @@ -140,7 +140,7 @@ func TestCreateNfDeploymentStatusDeploymentAvailable(t *testing.T) { smfDeployment.Status.Conditions = append(smfDeployment.Status.Conditions, condition) deployment.Status.Conditions = append(deployment.Status.Conditions, *deploymentCondition) - want := smfDeployment.Status.NFDeploymentStatus + want := smfDeployment.Status condition.Type = string(nephiov1alpha1.Available) condition.Status = metav1.ConditionTrue condition.Reason = "MinimumReplicasAvailable" @@ -176,7 +176,7 @@ func TestCreateNfDeploymentStatusDeploymentProcessing(t *testing.T) { smfDeployment.Status.Conditions = append(smfDeployment.Status.Conditions, condition) deployment.Status.Conditions = append(deployment.Status.Conditions, *deploymentCondition) - want := smfDeployment.Status.NFDeploymentStatus + want := smfDeployment.Status condition.Type = string(nephiov1alpha1.Reconciling) condition.Status = metav1.ConditionFalse condition.Reason = "MinimumReplicasNotAvailable" @@ -212,7 +212,7 @@ func TestCreateNfDeploymentStatusReplicaFailure(t *testing.T) { smfDeployment.Status.Conditions = append(smfDeployment.Status.Conditions, condition) deployment.Status.Conditions = append(deployment.Status.Conditions, *deploymentCondition) - want := smfDeployment.Status.NFDeploymentStatus + want := smfDeployment.Status condition.Type = string(nephiov1alpha1.Stalled) condition.Status = metav1.ConditionFalse condition.Reason = "MinimumReplicasNotAvailable" diff --git a/controllers/smf/templates.go b/controllers/nf/smf/templates.go similarity index 100% rename from controllers/smf/templates.go rename to controllers/nf/smf/templates.go diff --git a/controllers/upf/reconciler.go b/controllers/nf/upf/reconciler.go similarity index 68% rename from controllers/upf/reconciler.go rename to controllers/nf/upf/reconciler.go index 7e647e6..165e263 100644 --- a/controllers/upf/reconciler.go +++ b/controllers/nf/upf/reconciler.go @@ -39,51 +39,33 @@ type UPFDeploymentReconciler struct { Scheme *runtime.Scheme } -// Sets up the controller with the Manager -func (r *UPFDeploymentReconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(new(nephiov1alpha1.UPFDeployment)). - Owns(new(appsv1.Deployment)). - Owns(new(apiv1.ConfigMap)). - Complete(r) -} - -//+kubebuilder:rbac:groups=workload.nephio.org,resources=upfdeployments,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=workload.nephio.org,resources=upfdeployments/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=apps,resources=deployments/status,verbs=get -//+kubebuilder:rbac:groups="",resources=pods,verbs=get;list;watch -//+kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups="",resources=events,verbs=create;patch -//+kubebuilder:rbac:groups="k8s.cni.cncf.io",resources=network-attachment-definitions,verbs=get;list;watch - // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. // TODO(user): Modify the Reconcile function to compare the state specified by -// the UPFDeployment object against the actual cluster state, and then +// the NFDeployment object against the actual cluster state, and then // perform operations to make the cluster state reflect the state specified by // the user. // // For more details, check Reconcile and its Result here: // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.1/pkg/reconcile func (r *UPFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - log := log.FromContext(ctx).WithValues("UPFDeployment", req.NamespacedName) + log := log.FromContext(ctx).WithValues("NFDeployment", req.NamespacedName) - upfDeployment := new(nephiov1alpha1.UPFDeployment) - err := r.Client.Get(ctx, req.NamespacedName, upfDeployment) + nfDeployment := new(nephiov1alpha1.NFDeployment) + err := r.Client.Get(ctx, req.NamespacedName, nfDeployment) if err != nil { if k8serrors.IsNotFound(err) { - log.Info("UPFDeployment resource not found, ignoring because object must be deleted") + log.Info("NFDeployment resource not found, ignoring because object must be deleted") return reconcile.Result{}, nil } - log.Error(err, "Failed to get UPFDeployment") + log.Error(err, "Failed to get NFDeployment") return reconcile.Result{}, err } - namespace := upfDeployment.Namespace + namespace := nfDeployment.Namespace configMapFound := false - configMapName := upfDeployment.Name + configMapName := nfDeployment.Name var configMapVersion string currentConfigMap := new(apiv1.ConfigMap) if err := r.Client.Get(ctx, types.NamespacedName{Name: configMapName, Namespace: namespace}, currentConfigMap); err == nil { @@ -92,7 +74,7 @@ func (r *UPFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques } deploymentFound := false - deploymentName := upfDeployment.Name + deploymentName := nfDeployment.Name currentDeployment := new(appsv1.Deployment) if err := r.Client.Get(ctx, types.NamespacedName{Name: deploymentName, Namespace: namespace}, currentDeployment); err == nil { deploymentFound = true @@ -101,10 +83,10 @@ func (r *UPFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques if deploymentFound { deployment := currentDeployment.DeepCopy() - // Updating UPFDeployment status. On the first sets the first Condition to Reconciling. + // Updating NFDeployment status. On the first sets the first Condition to Reconciling. // On the subsequent runs it gets undelying depoyment Conditions and use the last one to decide if status has to be updated. if deployment.DeletionTimestamp == nil { - if err := r.syncStatus(ctx, deployment, upfDeployment); err != nil { + if err := r.syncStatus(ctx, deployment, nfDeployment); err != nil { log.Error(err, "Failed to update status") return reconcile.Result{}, err } @@ -123,12 +105,12 @@ func (r *UPFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques } } - if configMap, err := createConfigMap(log, upfDeployment); err == nil { + if configMap, err := createConfigMap(log, nfDeployment); err == nil { if !configMapFound { log.Info("Creating ConfigMap", "ConfigMap.namespace", configMap.Namespace, "ConfigMap.name", configMap.Name) - // Set the controller reference, specifying that UPFDeployment controling underlying ConfigMap - if err := ctrl.SetControllerReference(upfDeployment, configMap, r.Scheme); err != nil { + // Set the controller reference, specifying that NFDeployment controling underlying ConfigMap + if err := ctrl.SetControllerReference(nfDeployment, configMap, r.Scheme); err != nil { log.Error(err, "Got error while setting Owner reference on ConfigMap", "ConfigMap.namespace", configMap.Namespace, "ConfigMap.name", configMap.Name) } @@ -144,12 +126,12 @@ func (r *UPFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques return reconcile.Result{}, err } - if deployment, err := createDeployment(log, configMapVersion, upfDeployment); err == nil { + if deployment, err := createDeployment(log, configMapVersion, nfDeployment); err == nil { if !deploymentFound { // Only create Deployment in case all required NADs are present. Otherwise Requeue in 10 sec. - if ok := controllers.ValidateNetworkAttachmentDefinitions(ctx, r.Client, log, upfDeployment.Kind, deployment); ok { - // Set the controller reference, specifying that UPFDeployment controls the underlying Deployment - if err := ctrl.SetControllerReference(upfDeployment, deployment, r.Scheme); err != nil { + if ok := controllers.ValidateNetworkAttachmentDefinitions(ctx, r.Client, log, nfDeployment.Kind, deployment); ok { + // Set the controller reference, specifying that NFDeployment controls the underlying Deployment + if err := ctrl.SetControllerReference(nfDeployment, deployment, r.Scheme); err != nil { log.Error(err, "Got error while setting Owner reference on Deployment", "Deployment.namespace", deployment.Name, "Deployment.name", deployment.Name) } @@ -165,6 +147,7 @@ func (r *UPFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques return reconcile.Result{RequeueAfter: time.Duration(10) * time.Second}, nil } } else { + if err = r.Client.Update(ctx, deployment); err != nil { log.Error(err, "Failed to update Deployment", "Deployment.namespace", deployment.Namespace, "Deployment.name", deployment.Name) } @@ -177,11 +160,12 @@ func (r *UPFDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques return reconcile.Result{}, nil } -func (r *UPFDeploymentReconciler) syncStatus(ctx context.Context, deployment *appsv1.Deployment, upfDeployment *nephiov1alpha1.UPFDeployment) error { - if nfDeploymentStatus, update := createNfDeploymentStatus(deployment, upfDeployment); update { - upfDeployment = upfDeployment.DeepCopy() - upfDeployment.Status.NFDeploymentStatus = nfDeploymentStatus - return r.Status().Update(ctx, upfDeployment) +func (r *UPFDeploymentReconciler) syncStatus(ctx context.Context, deployment *appsv1.Deployment, nfDeployment *nephiov1alpha1.NFDeployment) error { + if nfDeploymentStatus, update := createNfDeploymentStatus(deployment, nfDeployment); update { + nfDeployment = nfDeployment.DeepCopy() + //nfDeployment.Status.NFDeploymentStatus = nfDeploymentStatus + nfDeployment.Status = nfDeploymentStatus + return r.Status().Update(ctx, nfDeployment) } else { return nil } diff --git a/controllers/upf/resources.go b/controllers/nf/upf/resources.go similarity index 94% rename from controllers/upf/resources.go rename to controllers/nf/upf/resources.go index de2db95..79f8a25 100644 --- a/controllers/upf/resources.go +++ b/controllers/nf/upf/resources.go @@ -28,7 +28,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func createDeployment(log logr.Logger, configMapVersion string, upfDeployment *nephiov1alpha1.UPFDeployment) (*appsv1.Deployment, error) { +func createDeployment(log logr.Logger, configMapVersion string, upfDeployment *nephiov1alpha1.NFDeployment) (*appsv1.Deployment, error) { namespace := upfDeployment.Namespace instanceName := upfDeployment.Name spec := upfDeployment.Spec @@ -139,7 +139,7 @@ func createDeployment(log logr.Logger, configMapVersion string, upfDeployment *n return deployment, nil } -func createConfigMap(log logr.Logger, upfDeployment *nephiov1alpha1.UPFDeployment) (*apiv1.ConfigMap, error) { +func createConfigMap(log logr.Logger, upfDeployment *nephiov1alpha1.NFDeployment) (*apiv1.ConfigMap, error) { namespace := upfDeployment.Namespace instanceName := upfDeployment.Name @@ -204,7 +204,7 @@ func createConfigMap(log logr.Logger, upfDeployment *nephiov1alpha1.UPFDeploymen return configMap, nil } -func createResourceRequirements(upfDeploymentSpec nephiov1alpha1.UPFDeploymentSpec) (int32, *apiv1.ResourceRequirements, error) { +func createResourceRequirements(upfDeploymentSpec nephiov1alpha1.NFDeploymentSpec) (int32, *apiv1.ResourceRequirements, error) { // TODO: Requirements should be calculated based on DL, UL // TODO: Increase number of recpicas based on NFDeployment.Capacity.MaxSessions @@ -243,7 +243,7 @@ func createResourceRequirements(upfDeploymentSpec nephiov1alpha1.UPFDeploymentSp return replicas, &resources, nil } -func createNetworkAttachmentDefinitionNetworks(templateName string, upfDeploymentSpec *nephiov1alpha1.UPFDeploymentSpec) (string, error) { +func createNetworkAttachmentDefinitionNetworks(templateName string, upfDeploymentSpec *nephiov1alpha1.NFDeploymentSpec) (string, error) { return controllers.CreateNetworkAttachmentDefinitionNetworks(templateName, map[string][]nephiov1alpha1.InterfaceConfig{ "n3": controllers.GetInterfaceConfigs(upfDeploymentSpec.Interfaces, "n3"), "n4": controllers.GetInterfaceConfigs(upfDeploymentSpec.Interfaces, "n4"), @@ -252,7 +252,7 @@ func createNetworkAttachmentDefinitionNetworks(templateName string, upfDeploymen }) } -func getNetworkInstances(upfDeploymentSpec nephiov1alpha1.UPFDeploymentSpec, interfaceName string) ([]nephiov1alpha1.NetworkInstance, bool) { +func getNetworkInstances(upfDeploymentSpec nephiov1alpha1.NFDeploymentSpec, interfaceName string) ([]nephiov1alpha1.NetworkInstance, bool) { var networkInstances []nephiov1alpha1.NetworkInstance for _, networkInstance := range upfDeploymentSpec.NetworkInstances { diff --git a/controllers/upf/resources_test.go b/controllers/nf/upf/resources_test.go similarity index 91% rename from controllers/upf/resources_test.go rename to controllers/nf/upf/resources_test.go index fa6517d..a30002b 100644 --- a/controllers/upf/resources_test.go +++ b/controllers/nf/upf/resources_test.go @@ -330,7 +330,7 @@ func TestGetUpfNetworkInstancesNoInstance(t *testing.T) { } } -func newUpfDeployment(name string) *nephiov1alpha1.UPFDeployment { +func newUpfDeployment(name string) *nephiov1alpha1.NFDeployment { interfaces := []nephiov1alpha1.InterfaceConfig{} n6int := newNxInterface("n6") n3int := newNxInterface("n3") @@ -340,41 +340,39 @@ func newUpfDeployment(name string) *nephiov1alpha1.UPFDeployment { interfaces = append(interfaces, n4int) dnnName := "apn-test" - return &nephiov1alpha1.UPFDeployment{ + return &nephiov1alpha1.NFDeployment{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: name + "-ns", }, - Spec: nephiov1alpha1.UPFDeploymentSpec{ - NFDeploymentSpec: nephiov1alpha1.NFDeploymentSpec{ - ConfigRefs: []apiv1.ObjectReference{}, - Capacity: &nephioreqv1alpha1.CapacitySpec{ - MaxUplinkThroughput: resource.MustParse("1G"), - MaxDownlinkThroughput: resource.MustParse("5G"), - MaxSessions: 1000, - MaxSubscribers: 1000, - MaxNFConnections: 2000, - }, - Interfaces: interfaces, - NetworkInstances: []nephiov1alpha1.NetworkInstance{ - { - Name: "vpc-internet", - Interfaces: []string{ - "n6", - }, - DataNetworks: []nephiov1alpha1.DataNetwork{ - { - Name: &dnnName, - Pool: []nephiov1alpha1.Pool{ - { - Prefix: "100.100.0.0/16", - }, + Spec: nephiov1alpha1.NFDeploymentSpec{ + ParametersRefs: []nephiov1alpha1.ObjectReference{}, + Capacity: &nephioreqv1alpha1.CapacitySpec{ + MaxUplinkThroughput: resource.MustParse("1G"), + MaxDownlinkThroughput: resource.MustParse("5G"), + MaxSessions: 1000, + MaxSubscribers: 1000, + MaxNFConnections: 2000, + }, + Interfaces: interfaces, + NetworkInstances: []nephiov1alpha1.NetworkInstance{ + { + Name: "vpc-internet", + Interfaces: []string{ + "n6", + }, + DataNetworks: []nephiov1alpha1.DataNetwork{ + { + Name: &dnnName, + Pool: []nephiov1alpha1.Pool{ + { + Prefix: "100.100.0.0/16", }, }, }, - BGP: nil, - Peers: []nephiov1alpha1.PeerConfig{}, }, + BGP: nil, + Peers: []nephiov1alpha1.PeerConfig{}, }, }, }, diff --git a/controllers/upf/status.go b/controllers/nf/upf/status.go similarity index 71% rename from controllers/upf/status.go rename to controllers/nf/upf/status.go index 1c878e9..b717c2e 100644 --- a/controllers/upf/status.go +++ b/controllers/nf/upf/status.go @@ -22,38 +22,38 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func createNfDeploymentStatus(deployment *appsv1.Deployment, upfDeployment *nephiov1alpha1.UPFDeployment) (nephiov1alpha1.NFDeploymentStatus, bool) { +func createNfDeploymentStatus(deployment *appsv1.Deployment, nfDeployment *nephiov1alpha1.NFDeployment) (nephiov1alpha1.NFDeploymentStatus, bool) { nfDeploymentStatus := nephiov1alpha1.NFDeploymentStatus{ ObservedGeneration: int32(deployment.Generation), - Conditions: upfDeployment.Status.Conditions, + Conditions: nfDeployment.Status.Conditions, } - // Return initial status if there are no status update happened for the UPFdeployment - if len(upfDeployment.Status.Conditions) == 0 { + // Return initial status if there are no status update happened for the NFdeployment + if len(nfDeployment.Status.Conditions) == 0 { nfDeploymentStatus.Conditions = append(nfDeploymentStatus.Conditions, metav1.Condition{ Type: string(nephiov1alpha1.Reconciling), Status: metav1.ConditionFalse, Reason: "MinimumReplicasNotAvailable", - Message: "UPFDeployment pod(s) is(are) starting.", + Message: "NFDeployment pod(s) is(are) starting.", LastTransitionTime: metav1.Now(), }) return nfDeploymentStatus, true - } else if (len(deployment.Status.Conditions) == 0) && (len(upfDeployment.Status.Conditions) > 0) { + } else if (len(deployment.Status.Conditions) == 0) && (len(nfDeployment.Status.Conditions) > 0) { return nfDeploymentStatus, false } // Check the last underlying Deployment status and deduce condition from it lastDeploymentCondition := deployment.Status.Conditions[0] - lastUpfDeploymentCondition := upfDeployment.Status.Conditions[len(upfDeployment.Status.Conditions)-1] + lastNfDeploymentCondition := nfDeployment.Status.Conditions[len(nfDeployment.Status.Conditions)-1] - // Deployemnt and UPFDeployment have different names for processing state, hence we check if one is processing another is reconciling, then state is equal - if (lastDeploymentCondition.Type == appsv1.DeploymentProgressing) && (lastUpfDeploymentCondition.Type == string(nephiov1alpha1.Reconciling)) { + // Deployemnt and NFDeployment have different names for processing state, hence we check if one is processing another is reconciling, then state is equal + if (lastDeploymentCondition.Type == appsv1.DeploymentProgressing) && (lastNfDeploymentCondition.Type == string(nephiov1alpha1.Reconciling)) { return nfDeploymentStatus, false } // if both status types are Available, don't update. - if string(lastDeploymentCondition.Type) == string(lastUpfDeploymentCondition.Type) { + if string(lastDeploymentCondition.Type) == string(lastNfDeploymentCondition.Type) { return nfDeploymentStatus, false } @@ -63,7 +63,7 @@ func createNfDeploymentStatus(deployment *appsv1.Deployment, upfDeployment *neph Type: string(nephiov1alpha1.Available), Status: metav1.ConditionTrue, Reason: "MinimumReplicasAvailable", - Message: "UPFDeployment pods are available.", + Message: "NFDeployment pods are available.", LastTransitionTime: metav1.Now(), }) @@ -72,7 +72,7 @@ func createNfDeploymentStatus(deployment *appsv1.Deployment, upfDeployment *neph Type: string(nephiov1alpha1.Reconciling), Status: metav1.ConditionFalse, Reason: "MinimumReplicasNotAvailable", - Message: "UPFDeployment pod(s) is(are) starting.", + Message: "NFDeployment pod(s) is(are) starting.", LastTransitionTime: metav1.Now(), }) @@ -81,10 +81,9 @@ func createNfDeploymentStatus(deployment *appsv1.Deployment, upfDeployment *neph Type: string(nephiov1alpha1.Stalled), Status: metav1.ConditionFalse, Reason: "MinimumReplicasNotAvailable", - Message: "UPFDeployment pod(s) is(are) failing.", + Message: "NFDeployment pod(s) is(are) failing.", LastTransitionTime: metav1.Now(), }) } - return nfDeploymentStatus, true } diff --git a/controllers/upf/status_test.go b/controllers/nf/upf/status_test.go similarity index 69% rename from controllers/upf/status_test.go rename to controllers/nf/upf/status_test.go index 8608e83..b9ea7ee 100644 --- a/controllers/upf/status_test.go +++ b/controllers/nf/upf/status_test.go @@ -21,133 +21,135 @@ import ( "testing" nephiov1alpha1 "github.com/nephio-project/api/nf_deployments/v1alpha1" + // nephioreqv1alpha1 "github.com/nephio-project/api/nf_requirements/v1alpha1" appsv1 "k8s.io/api/apps/v1" + // "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestCreateNfDeploymentStatusFirst(t *testing.T) { - upfDeployment := newUpfDeployment("test-upf-deployment") + nfDeployment := newUpfDeployment("test-nf-deployment") deployment := new(appsv1.Deployment) want := nephiov1alpha1.NFDeploymentStatus{ ObservedGeneration: int32(deployment.Generation), - Conditions: upfDeployment.Status.Conditions, + Conditions: nfDeployment.Status.Conditions, } var condition metav1.Condition condition.Type = string(nephiov1alpha1.Reconciling) condition.Status = metav1.ConditionFalse condition.Reason = "MinimumReplicasNotAvailable" - condition.Message = "UPFDeployment pod(s) is(are) starting." - // condition.LastTransitionTime = metav1.Now() + condition.Message = "NFDeployment pod(s) is(are) starting." + want.Conditions = append(want.Conditions, condition) - got, b := createNfDeploymentStatus(deployment, upfDeployment) + got, b := createNfDeploymentStatus(deployment, nfDeployment) gotCondition := got.Conditions[0] gotCondition.LastTransitionTime = metav1.Time{} if !reflect.DeepEqual(gotCondition, condition) { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, upfDeployment, got, want) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, got, want) } if !b { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, upfDeployment, b, true) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, b, true) } } func TestCreateNfDeploymentStatusDeploymentNotReady(t *testing.T) { - upfDeployment := newUpfDeployment("test-upf-deployment") + nfDeployment := newUpfDeployment("test-nf-deployment") deployment := new(appsv1.Deployment) var condition metav1.Condition condition.Type = string(nephiov1alpha1.Reconciling) condition.Status = metav1.ConditionFalse condition.Reason = "MinimumReplicasNotAvailable" - condition.Message = "UPFDeployment pod(s) is(are) starting." + condition.Message = "NFDeployment pod(s) is(are) starting." condition.LastTransitionTime = metav1.Now() - upfDeployment.Status.Conditions = append(upfDeployment.Status.Conditions, condition) + nfDeployment.Status.Conditions = append(nfDeployment.Status.Conditions, condition) - want := upfDeployment.Status.NFDeploymentStatus + want := nfDeployment.Status - got, b := createNfDeploymentStatus(deployment, upfDeployment) + got, b := createNfDeploymentStatus(deployment, nfDeployment) if !reflect.DeepEqual(got, want) { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, upfDeployment, got, want) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, got, want) } if b { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, upfDeployment, b, false) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, b, false) } } func TestCreateNfDeploymentStatusProcessing(t *testing.T) { - upfDeployment := newUpfDeployment("test-upf-deployment") + nfDeployment := newUpfDeployment("test-nf-deployment") deployment := new(appsv1.Deployment) var condition metav1.Condition condition.Type = string(nephiov1alpha1.Reconciling) deploymentCondition := &appsv1.DeploymentCondition{} deploymentCondition.Type = appsv1.DeploymentProgressing - upfDeployment.Status.Conditions = append(upfDeployment.Status.Conditions, condition) + nfDeployment.Status.Conditions = append(nfDeployment.Status.Conditions, condition) deployment.Status.Conditions = append(deployment.Status.Conditions, *deploymentCondition) - want := upfDeployment.Status.NFDeploymentStatus + want := nfDeployment.Status - got, b := createNfDeploymentStatus(deployment, upfDeployment) + got, b := createNfDeploymentStatus(deployment, nfDeployment) if !reflect.DeepEqual(got, want) { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, upfDeployment, got, want) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, got, want) } if b { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, upfDeployment, b, false) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, b, false) } } func TestCreateNfDeploymentStatusAvailable(t *testing.T) { - upfDeployment := newUpfDeployment("test-upf-deployment") + nfDeployment := newUpfDeployment("test-nf-deployment") deployment := new(appsv1.Deployment) var condition metav1.Condition condition.Type = string(nephiov1alpha1.Available) deploymentCondition := &appsv1.DeploymentCondition{} deploymentCondition.Type = appsv1.DeploymentAvailable - upfDeployment.Status.Conditions = append(upfDeployment.Status.Conditions, condition) + nfDeployment.Status.Conditions = append(nfDeployment.Status.Conditions, condition) deployment.Status.Conditions = append(deployment.Status.Conditions, *deploymentCondition) - want := upfDeployment.Status.NFDeploymentStatus + want := nfDeployment.Status - got, b := createNfDeploymentStatus(deployment, upfDeployment) + got, b := createNfDeploymentStatus(deployment, nfDeployment) if !reflect.DeepEqual(got, want) { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, upfDeployment, got, want) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, got, want) } if b { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, upfDeployment, b, false) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, b, false) } } func TestCreateNfDeploymentStatusDeploymentAvailable(t *testing.T) { - upfDeployment := newUpfDeployment("test-upf-deployment") + nfDeployment := newUpfDeployment("test-nf-deployment") deployment := new(appsv1.Deployment) var condition metav1.Condition condition.Type = string(nephiov1alpha1.Reconciling) condition.Status = metav1.ConditionFalse condition.Reason = "MinimumReplicasNotAvailable" - condition.Message = "UPFDeployment pod(s) is(are) starting." + condition.Message = "NFDeployment pod(s) is(are) starting." deploymentCondition := &appsv1.DeploymentCondition{} deploymentCondition.Type = appsv1.DeploymentAvailable deploymentCondition.Reason = "MinimumReplicasAvailable" - upfDeployment.Status.Conditions = append(upfDeployment.Status.Conditions, condition) + nfDeployment.Status.Conditions = append(nfDeployment.Status.Conditions, condition) deployment.Status.Conditions = append(deployment.Status.Conditions, *deploymentCondition) - want := upfDeployment.Status.NFDeploymentStatus + want := nfDeployment.Status condition.Type = string(nephiov1alpha1.Available) condition.Status = metav1.ConditionTrue condition.Reason = "MinimumReplicasAvailable" - condition.Message = "UPFDeployment pods are available." + condition.Message = "NFDeployment pods are available." want.Conditions = append(want.Conditions, condition) - got, b := createNfDeploymentStatus(deployment, upfDeployment) + got, b := createNfDeploymentStatus(deployment, nfDeployment) gotCondition := got.Conditions[1] gotCondition.LastTransitionTime = metav1.Time{} @@ -155,35 +157,35 @@ func TestCreateNfDeploymentStatusDeploymentAvailable(t *testing.T) { got.Conditions = append(got.Conditions, gotCondition) if !reflect.DeepEqual(got, want) { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, upfDeployment, got, want) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, got, want) } if !b { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, upfDeployment, b, true) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, b, true) } } func TestCreateNfDeploymentStatusDeploymentProcessing(t *testing.T) { - upfDeployment := newUpfDeployment("test-upf-deployment") + nfDeployment := newUpfDeployment("test-nf-deployment") deployment := new(appsv1.Deployment) var condition metav1.Condition condition.Type = string(nephiov1alpha1.Available) condition.Status = metav1.ConditionTrue condition.Reason = "MinimumReplicasAvailable" - condition.Message = "UPFDeployment pods are available" + condition.Message = "NFDeployment pods are available" deploymentCondition := &appsv1.DeploymentCondition{} deploymentCondition.Type = appsv1.DeploymentProgressing - upfDeployment.Status.Conditions = append(upfDeployment.Status.Conditions, condition) + nfDeployment.Status.Conditions = append(nfDeployment.Status.Conditions, condition) deployment.Status.Conditions = append(deployment.Status.Conditions, *deploymentCondition) - want := upfDeployment.Status.NFDeploymentStatus + want := nfDeployment.Status condition.Type = string(nephiov1alpha1.Reconciling) condition.Status = metav1.ConditionFalse condition.Reason = "MinimumReplicasNotAvailable" - condition.Message = "UPFDeployment pod(s) is(are) starting." + condition.Message = "NFDeployment pod(s) is(are) starting." want.Conditions = append(want.Conditions, condition) - got, b := createNfDeploymentStatus(deployment, upfDeployment) + got, b := createNfDeploymentStatus(deployment, nfDeployment) gotCondition := got.Conditions[1] gotCondition.LastTransitionTime = metav1.Time{} @@ -191,35 +193,35 @@ func TestCreateNfDeploymentStatusDeploymentProcessing(t *testing.T) { got.Conditions = append(got.Conditions, gotCondition) if !reflect.DeepEqual(got, want) { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, upfDeployment, got, want) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, got, want) } if !b { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, upfDeployment, b, true) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, b, true) } } func TestCreateNfDeploymentStatusReplicaFailure(t *testing.T) { - upfDeployment := newUpfDeployment("test-upf-deployment") + nfDeployment := newUpfDeployment("test-nf-deployment") deployment := new(appsv1.Deployment) var condition metav1.Condition condition.Type = string(nephiov1alpha1.Available) condition.Status = metav1.ConditionTrue condition.Reason = "MinimumReplicasAvailable" - condition.Message = "UPFDeployment pods are available" + condition.Message = "NFDeployment pods are available" deploymentCondition := &appsv1.DeploymentCondition{} deploymentCondition.Type = appsv1.DeploymentReplicaFailure - upfDeployment.Status.Conditions = append(upfDeployment.Status.Conditions, condition) + nfDeployment.Status.Conditions = append(nfDeployment.Status.Conditions, condition) deployment.Status.Conditions = append(deployment.Status.Conditions, *deploymentCondition) - want := upfDeployment.Status.NFDeploymentStatus + want := nfDeployment.Status condition.Type = string(nephiov1alpha1.Stalled) condition.Status = metav1.ConditionFalse condition.Reason = "MinimumReplicasNotAvailable" - condition.Message = "UPFDeployment pod(s) is(are) failing." + condition.Message = "NFDeployment pod(s) is(are) failing." want.Conditions = append(want.Conditions, condition) - got, b := createNfDeploymentStatus(deployment, upfDeployment) + got, b := createNfDeploymentStatus(deployment, nfDeployment) gotCondition := got.Conditions[1] gotCondition.LastTransitionTime = metav1.Time{} @@ -227,9 +229,9 @@ func TestCreateNfDeploymentStatusReplicaFailure(t *testing.T) { got.Conditions = append(got.Conditions, gotCondition) if !reflect.DeepEqual(got, want) { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, upfDeployment, got, want) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, got, want) } if !b { - t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, upfDeployment, b, true) + t.Errorf("createNfDeploymentStatus(%v, %v) returned %v, want %v", deployment, nfDeployment, b, true) } } diff --git a/controllers/upf/templates.go b/controllers/nf/upf/templates.go similarity index 100% rename from controllers/upf/templates.go rename to controllers/nf/upf/templates.go diff --git a/free5gc-operator/main.go b/free5gc-operator/main.go index 96dfcd4..8a77b11 100644 --- a/free5gc-operator/main.go +++ b/free5gc-operator/main.go @@ -26,9 +26,7 @@ import ( nephiov1alpha1 "github.com/nephio-project/api/nf_deployments/v1alpha1" refv1alpha1 "github.com/nephio-project/api/references/v1alpha1" - "github.com/nephio-project/free5gc/controllers/amf" - "github.com/nephio-project/free5gc/controllers/smf" - "github.com/nephio-project/free5gc/controllers/upf" + "github.com/nephio-project/free5gc/controllers/nf" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" @@ -92,19 +90,10 @@ func main() { } schemeBuilder := &runscheme.Builder{GroupVersion: nephiov1alpha1.GroupVersion} - schemeBuilder.Register(&nephiov1alpha1.UPFDeployment{}, &nephiov1alpha1.UPFDeploymentList{}) - if err := schemeBuilder.AddToScheme(manager.GetScheme()); err != nil { - fail(err, "Not able to register UPFDeployment kind") - } - schemeBuilder.Register(&nephiov1alpha1.SMFDeployment{}, &nephiov1alpha1.SMFDeploymentList{}) + schemeBuilder.Register(&nephiov1alpha1.NFDeployment{}, &nephiov1alpha1.NFDeploymentList{}) if err := schemeBuilder.AddToScheme(manager.GetScheme()); err != nil { - fail(err, "Not able to register SMFDeployment kind") - } - - schemeBuilder.Register(&nephiov1alpha1.AMFDeployment{}, &nephiov1alpha1.AMFDeploymentList{}) - if err := schemeBuilder.AddToScheme(manager.GetScheme()); err != nil { - fail(err, "Not able to register AMFDeployment kind") + fail(err, "Not able to register NFDeployment kind") } schemeBuilder = &runscheme.Builder{GroupVersion: refv1alpha1.GroupVersion} @@ -113,27 +102,14 @@ func main() { fail(err, "Not able to register Config.ref kind") } - if err = (&upf.UPFDeploymentReconciler{ - Client: manager.GetClient(), - Scheme: manager.GetScheme(), - }).SetupWithManager(manager); err != nil { - fail(err, "unable to create controller", "controller", "UPFDeployment") - } - - if err = (&smf.SMFDeploymentReconciler{ + if err = (&nf.NFDeploymentReconciler{ Client: manager.GetClient(), Scheme: manager.GetScheme(), }).SetupWithManager(manager); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "SMFDeployment") + setupLog.Error(err, "unable to create controller", "controller", "NFDeployment") os.Exit(1) } - if err = (&amf.AMFDeploymentReconciler{ - Client: manager.GetClient(), - Scheme: manager.GetScheme(), - }).SetupWithManager(manager); err != nil { - fail(err, "unable to create controller", "controller", "AMFDeployment") - } //+kubebuilder:scaffold:builder if err := manager.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/go.mod b/go.mod index 9a1dc9a..6d46064 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,8 @@ go 1.20 require ( github.com/go-logr/logr v1.2.4 - github.com/nephio-project/api v0.0.0-20230622115552-0304af432fd3 + //github.com/nephio-project/api v0.0.0-20230622115552-0304af432fd3 + github.com/nephio-project/api v1.0.1-0.20231006162045-9ad2d0db2a8d github.com/onsi/ginkgo/v2 v2.10.0 github.com/onsi/gomega v1.27.8 k8s.io/api v0.27.2 diff --git a/go.sum b/go.sum index d95aab7..f210e1e 100644 --- a/go.sum +++ b/go.sum @@ -128,6 +128,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/nephio-project/api v0.0.0-20230622115552-0304af432fd3 h1:7e6RZ+nQJLkB5NzbY8pGSxhzB2OkC3It//z8t3OE23g= github.com/nephio-project/api v0.0.0-20230622115552-0304af432fd3/go.mod h1:9w+JbXeyiT3KZrrXab0pzaWtiUk4upvgLzpqOtSmbpI= +github.com/nephio-project/api v1.0.1-0.20231006162045-9ad2d0db2a8d h1:I8j2xAJWpBpI5b/GOEdANY/9k4ORzmUEd1HuiFDVGi0= +github.com/nephio-project/api v1.0.1-0.20231006162045-9ad2d0db2a8d/go.mod h1:9w+JbXeyiT3KZrrXab0pzaWtiUk4upvgLzpqOtSmbpI= github.com/nokia/k8s-ipam v0.0.4-0.20230608184434-0c910788bac7 h1:ZoUMFeP4Hhh35LMvSO4+0+y+lNw0G4fhus15WpOCF8I= github.com/nokia/k8s-ipam v0.0.4-0.20230608184434-0c910788bac7/go.mod h1:ZVMmhD6jllAAO3YGIZFXUQbKRtEiIYgZ772bn/1GVz4= github.com/onsi/ginkgo/v2 v2.10.0 h1:sfUl4qgLdvkChZrWCYndY2EAu9BRIw1YphNAzy1VNWs= diff --git a/test/amf1-n2.yaml b/test/amf1-n2.yaml index 09c4708..3673794 100644 --- a/test/amf1-n2.yaml +++ b/test/amf1-n2.yaml @@ -16,7 +16,7 @@ kind: NetworkAttachmentDefinition metadata: namespace: free5gc - name: amf-1-n2 + name: free5gc-amf-1-n2 spec: config: '{ diff --git a/test/amf1.yaml b/test/amf1.yaml index 604d4b2..68d6373 100644 --- a/test/amf1.yaml +++ b/test/amf1.yaml @@ -1,13 +1,14 @@ apiVersion: workload.nephio.org/v1alpha1 -kind: AMFDeployment +kind: NFDeployment metadata: namespace: free5gc - name: amf-1 + name: free5gc-amf-1 annotations: config.kubernetes.io/local-config: "false" spec: + provider: "amf.free5gc.nephio.org" capacity: maxSubscribers: 1000 interfaces: @@ -20,4 +21,4 @@ spec: - name: vpc-internal interfaces: - n2 - configRefs: + parametersRefs: diff --git a/test/configref1.yaml b/test/configref1.yaml index 1ede0ec..36f967d 100644 --- a/test/configref1.yaml +++ b/test/configref1.yaml @@ -6,7 +6,7 @@ metadata: spec: config: apiVersion: workload.nephio.org/v1alpha1 - kind: UPFDeployment + kind: NFDeployment metadata: name: free5gc-upf-1 namespace: upf-1 diff --git a/test/smf1-n4.yaml b/test/smf1-n4.yaml index 322d6c1..fb67b09 100644 --- a/test/smf1-n4.yaml +++ b/test/smf1-n4.yaml @@ -16,7 +16,7 @@ kind: NetworkAttachmentDefinition metadata: namespace: free5gc - name: smf-1-n4 + name: free5gc-smf-1-n4 spec: config: '{ @@ -25,7 +25,7 @@ spec: { "type": "macvlan", "capabilities": { "ips": true }, - "master": "ens33", + "master": "eth0", "mode": "bridge", "ipam": { "type": "static", diff --git a/test/smf1.yaml b/test/smf1.yaml index 9c852c2..c7b3f71 100644 --- a/test/smf1.yaml +++ b/test/smf1.yaml @@ -1,13 +1,14 @@ apiVersion: workload.nephio.org/v1alpha1 -kind: SMFDeployment +kind: NFDeployment metadata: namespace: free5gc - name: smf-1 + name: free5gc-smf-1 annotations: config.kubernetes.io/local-config: "false" spec: + provider: "smf.free5gc.nephio.org" capacity: maxSessions: 5000 maxNFConnections: 100 @@ -25,12 +26,7 @@ spec: - name: internet pool: - prefix: "10.200.50.0/24" - configRefs: - - apiVersion: "ref.nephio.org/v1alpha1" - kind: Config - name: smf-config-ref - namespace: free5gc - - apiVersion: "ref.nephio.org/v1alpha1" - kind: Config - name: smf-config-ref-2 - namespace: free5gc + parametersRefs: + - apiVersion: "ref.nephio.org/v1alpha1" + kind: Config + name: smf-config-ref diff --git a/test/upf1-n3.yaml b/test/upf1-n3.yaml index f912370..f0c79ae 100644 --- a/test/upf1-n3.yaml +++ b/test/upf1-n3.yaml @@ -16,7 +16,7 @@ kind: NetworkAttachmentDefinition metadata: namespace: free5gc - name: upf-1-n3 + name: free5gc-upf-1-n3 spec: config: '{ diff --git a/test/upf1-n4.yaml b/test/upf1-n4.yaml index 1b3d18b..f3c6fe2 100644 --- a/test/upf1-n4.yaml +++ b/test/upf1-n4.yaml @@ -16,7 +16,7 @@ kind: NetworkAttachmentDefinition metadata: namespace: free5gc - name: upf-1-n4 + name: free5gc-upf-1-n4 spec: config: '{ diff --git a/test/upf1-n6.yaml b/test/upf1-n6.yaml index 249083f..a5a7313 100644 --- a/test/upf1-n6.yaml +++ b/test/upf1-n6.yaml @@ -16,7 +16,7 @@ kind: NetworkAttachmentDefinition metadata: namespace: free5gc - name: upf-1-n6 + name: free5gc-upf-1-n6 spec: config: '{ diff --git a/test/upf1.yaml b/test/upf1.yaml index 4cbce7b..b6ea7cf 100644 --- a/test/upf1.yaml +++ b/test/upf1.yaml @@ -1,31 +1,32 @@ apiVersion: workload.nephio.org/v1alpha1 -kind: UPFDeployment +kind: NFDeployment metadata: namespace: free5gc - name: upf-1 + name: free5gc-upf-1 annotations: config.kubernetes.io/local-config: "false" spec: + provider: "upf.free5gc.nephio.org" capacity: maxUplinkThroughput: 3G maxDownlinkThroughput: 1G interfaces: - name: n3 ipv4: - address: 13.0.0.2/24 - gateway: 13.0.0.1 - vlanID: 13 + address: 10.10.50.2/24 + gateway: 10.10.50.1 + vlanID: 12 - name: n4 ipv4: - address: 14.0.0.2/24 - gateway: 14.0.0.1 + address: 10.10.30.2/24 + gateway: 10.10.30.1 vlanID: 14 - name: n6 ipv4: - address: 16.0.0.2/24 - gateway: 16.0.0.1 + address: 10.10.40.2/24 + gateway: 10.10.40.1 vlanID: 16 networkInstances: - name: vpc-ran @@ -41,4 +42,4 @@ spec: - name: internet pool: - prefix: 10.10.0.0/16 - configRefs: + parametersRefs: diff --git a/test/upf2-n3.yaml b/test/upf2-n3.yaml index 69b9b1f..795bcfa 100644 --- a/test/upf2-n3.yaml +++ b/test/upf2-n3.yaml @@ -16,7 +16,7 @@ kind: NetworkAttachmentDefinition metadata: namespace: free5gc - name: upf-2-n3 + name: free5gc-upf-2-n3 spec: config: '{ diff --git a/test/upf2-n4.yaml b/test/upf2-n4.yaml index 07addfd..976726a 100644 --- a/test/upf2-n4.yaml +++ b/test/upf2-n4.yaml @@ -16,7 +16,7 @@ kind: NetworkAttachmentDefinition metadata: namespace: free5gc - name: upf-2-n4 + name: free5gc-upf-2-n4 spec: config: '{ diff --git a/test/upf2-n6.yaml b/test/upf2-n6.yaml index 2229bbd..a167f32 100644 --- a/test/upf2-n6.yaml +++ b/test/upf2-n6.yaml @@ -16,7 +16,7 @@ kind: NetworkAttachmentDefinition metadata: namespace: free5gc - name: upf-2-n6 + name: free5gc-upf-2-n6 spec: config: '{ @@ -25,7 +25,7 @@ spec: { "type": "macvlan", "capabilities": { "ips": true }, - "master": "eth0", + "master": "eno1", "mode": "bridge", "ipam": { "type": "static",