Skip to content

Commit

Permalink
First implementation of the DNN KRM function
Browse files Browse the repository at this point in the history
  • Loading branch information
kispaljr committed Apr 19, 2023
1 parent f8a320a commit 581f821
Show file tree
Hide file tree
Showing 17 changed files with 618 additions and 6 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@
# Tox environments
.tox/
*.dic
/.vscode
_actual_output.yaml
15 changes: 15 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ require (
github.com/GoogleContainerTools/kpt-functions-sdk/go/fn v0.0.0-20230302070146-e8e9cb3c3ae2
github.com/google/go-cmp v0.5.9
github.com/nephio-project/api v0.0.0-20230404174821-1fa5d1c78b70
github.com/nephio-project/nephio-controller-poc v0.0.0-20221111013453-5a31b4722094
github.com/nokia/k8s-ipam v0.0.4-0.20230416191338-dcd944a8d636
github.com/stretchr/testify v1.8.1
k8s.io/api v0.26.1
k8s.io/apimachinery v0.26.3
Expand All @@ -16,6 +18,8 @@ require (
require (
github.com/GoogleContainerTools/kpt-functions-sdk/go/api v0.0.0-20220720212527-133180134b93 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
Expand All @@ -25,22 +29,33 @@ require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/gnostic v0.6.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/hansthienpondt/nipam v0.0.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kentik/patricia v1.2.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/xlab/treeprint v1.1.0 // indirect
go4.org/netipx v0.0.0-20220925034521-797b0c90d8ab // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/term v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/time v0.3.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect
google.golang.org/grpc v1.49.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/client-go v0.26.1 // indirect
k8s.io/klog/v2 v2.90.0 // indirect
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect
Expand Down
62 changes: 62 additions & 0 deletions go.sum

Large diffs are not rendered by default.

64 changes: 64 additions & 0 deletions krm-functions/dnn-fn/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# some-function-name

Note: Please ensure you follow the [kpt doc style guide].

## Overview

<!--mdtogo:Short-->

Explain what this function does in one or two sentences.

<!--mdtogo-->

Describe why the user should care about this function.

What problem does it solve?

Provide some context (e.g. In the `gatekeeper` function, explain what's
is `Gatekeeper` project)

[//]: <> (Note: The content between `<!--mdtogo:Short-->` and the following
`<!--mdtogo-->` will be used as the short description for the command.)

<!--mdtogo:Long-->

## Usage

How do I use this function?

Explain what does it do in details.

Is this function meant to be used declaratively, imperatively or both?

### FunctionConfig

Omit this section, if the function doesn't support any `functionConfigs`.
Otherwise, explain the function config and behavior for this function in detail.
For each field in the function config, specify:

- An example value
- Whether it is optional, and if so, the default value

If showing the function orchestrator (e.g. kpt) can make it clear about how to
use the function, it's recommended to use it.

[//]: <> (Note: The content between `<!--mdtogo:Long-->` and the following
`<!--mdtogo-->` will be used as the long description for the command.)

<!--mdtogo-->

## Examples

<!--mdtogo:Examples-->

Omit this section if you are providing complete example kpt packages which are
linked from the catalog site.

Otherwise, provide inline examples in this section.

[//]: <> (Note: The content between `<!--mdtogo:Examples-->` and the following
`<!--mdtogo-->` will be used as the examples for the command.)

<!--mdtogo-->

[kpt doc style guide]: https://github.com/GoogleContainerTools/kpt/blob/main/docs/style-guides/docs.md
3 changes: 0 additions & 3 deletions krm-functions/dnn-fn/go.mod

This file was deleted.

35 changes: 35 additions & 0 deletions krm-functions/dnn-fn/golden_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
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 main

import (
"testing"

"github.com/GoogleContainerTools/kpt-functions-sdk/go/fn"
"github.com/GoogleContainerTools/kpt-functions-sdk/go/fn/testhelpers"
)

const TestDataPath = "testdata"

func TestFunction(t *testing.T) {
//fnRunner := fn.WithContext(context.TODO(), &DnnFn{})
fnRunner := fn.ResourceListProcessorFunc(Run)

// This golden test expects each sub-directory of `testdata` can has its input resources (in `resources.yaml`)
// be modified to the output resources (in `_expected.yaml`).
testhelpers.RunGoldenTests(t, TestDataPath, fnRunner)
}
183 changes: 183 additions & 0 deletions krm-functions/dnn-fn/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/*
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 main

import (
"os"

"fmt"

"github.com/GoogleContainerTools/kpt-functions-sdk/go/fn"
nephioreqv1alpha1 "github.com/nephio-project/api/nf_requirements/v1alpha1"
infrav1alpha1 "github.com/nephio-project/nephio-controller-poc/apis/infra/v1alpha1"
kptcondsdk "github.com/nephio-project/nephio/krm-functions/lib/condkptsdk"
ipamv1alpha1 "github.com/nokia/k8s-ipam/apis/alloc/ipam/v1alpha1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// var _ fn.Runner = &DnnFn{}

const (
// TODO: this should go to a lib somewhere
SiteAnnotationKey = "nephio.org/site"
)

type DnnFn struct {
sdk kptcondsdk.KptCondSDK
site string
}

func Run(rl *fn.ResourceList) (bool, error) {
myFn := DnnFn{}
var err error
myFn.sdk, err = kptcondsdk.New(
rl,
&kptcondsdk.Config{
For: corev1.ObjectReference{
APIVersion: nephioreqv1alpha1.GroupVersion.Identifier(),
Kind: nephioreqv1alpha1.DataNetworkKind,
},
Owns: map[corev1.ObjectReference]kptcondsdk.ResourceKind{
{
APIVersion: ipamv1alpha1.GroupVersion.Identifier(),
Kind: ipamv1alpha1.IPAllocationKind,
}: kptcondsdk.ChildRemote,
},
Watch: map[corev1.ObjectReference]kptcondsdk.WatchCallbackFn{
{
APIVersion: infrav1alpha1.GroupVersion.Identifier(),
Kind: "ClusterContext",
}: myFn.ClusterContextCallbackFn,
},
PopulateOwnResourcesFn: myFn.desiredOwnedResourceList,
GenerateResourceFn: myFn.updateDnnResource,
},
)
if err != nil {
rl.Results.ErrorE(err)
return false, err
}
myFn.sdk.Run()
return true, nil
}

func (f *DnnFn) ClusterContextCallbackFn(o *fn.KubeObject) error {
var cluster infrav1alpha1.ClusterContext
err := o.As(&cluster)
if err != nil {
return err
}
f.site = *cluster.Spec.SiteCode
return nil
}

func (f *DnnFn) desiredOwnedResourceList(o *fn.KubeObject) ([]*fn.KubeObject, error) {
resources := []*fn.KubeObject{}

// get "parent"| DNN struct
var dnn nephioreqv1alpha1.DataNetwork
err := o.As(&dnn)
if err != nil {
return nil, err
}

// add "network" IPAllocation
ipalloc := ipamv1alpha1.BuildIPAllocation(
metav1.ObjectMeta{
Name: fmt.Sprintf("%s-network", dnn.Name),
},
ipamv1alpha1.IPAllocationSpec{
PrefixKind: ipamv1alpha1.PrefixKindNetwork,
NetworkInstance: &corev1.ObjectReference{
Name: dnn.Spec.NetworkInstance.Name,
},
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
SiteAnnotationKey: f.site,
},
},
},
ipamv1alpha1.IPAllocationStatus{},
)

ipallocObj, err := fn.NewFromTypedObject(ipalloc)
if err != nil {
return nil, err
}
resources = append(resources, ipallocObj)

// add IPAllocation for each pool
for _, pool := range dnn.Spec.Pools {
ipalloc := ipamv1alpha1.BuildIPAllocation(
metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%s", dnn.Name, pool.Name),
},
ipamv1alpha1.IPAllocationSpec{
PrefixKind: ipamv1alpha1.PrefixKindPool,
NetworkInstance: &corev1.ObjectReference{
Name: dnn.Spec.NetworkInstance.Name,
},
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"nephio.org/site": f.site,
},
},
PrefixLength: pool.PrefixLength,
},
ipamv1alpha1.IPAllocationStatus{},
)

ipallocObj, err := fn.NewFromTypedObject(ipalloc)
if err != nil {
return nil, err
}
resources = append(resources, ipallocObj)
}
return resources, nil
}

func (f *DnnFn) updateDnnResource(dnnObj *fn.KubeObject, owned_ []*fn.KubeObject) (*fn.KubeObject, error) {
owned := fn.KubeObjects(owned_)
// we expect a for object here
if dnnObj == nil {
return nil, fmt.Errorf("expected a for object but got nil")
}
for _, o := range owned.Where(fn.IsGroupVersionKind(ipamv1alpha1.IPAllocationGroupVersionKind)) {
var ipalloc ipamv1alpha1.IPAllocation
err := o.As(&ipalloc)
if err != nil {
return nil, err
}
prefix := ipalloc.Status.AllocatedPrefix

// TODO: create DNN manipulation interface and the manipulation via that
// TODO: add allocatedPrefixes field to DataNetworkStatus
// TODO: parse the name of the pool back from ipalloc.Name
dnnObj.SetNestedField(prefix, "status", "allocatedPrefixes", ipalloc.Name)
}
return dnnObj, nil
}

func main() {
// runner := fn.WithContext(context.Background(), &DnnFn{})
runner := fn.ResourceListProcessorFunc(Run)

if err := fn.AsMain(runner); err != nil {
os.Exit(1)
}
}
12 changes: 12 additions & 0 deletions krm-functions/dnn-fn/testdata/test1/Kptfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: kpt.dev/v1
kind: Kptfile
# comment A
metadata:
name: pkg-upf
#commentB
annotations:
config.kubernetes.io/local-config: "true"
info:
description: upf package example
pipeline: {}

Loading

0 comments on commit 581f821

Please sign in to comment.