Skip to content

Commit 906313d

Browse files
authored
[Multitenancy]: Add PNI CRD (#2134)
* ADD CNI PRD * update manifest * add doc.go * ADD CNI PRD * updatepodnetwork ffiel as required * update manifest * fix crdgen --------- Signed-off-by: aggarwal0009 <[email protected]>
1 parent 9612960 commit 906313d

File tree

11 files changed

+420
-0
lines changed

11 files changed

+420
-0
lines changed

.github/workflows/crdgen.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ jobs:
2626
run: make -C crd/nodenetworkconfig
2727
- name: Regenerate MultitenantNetworkContainer CRD
2828
run: make -C crd/multitenantnetworkcontainer
29+
- name: Regenerate PodNetworkInstance CRD
30+
run: make -C crd/external/podnetworkinstance
2931
- name: Regenerate PodNetwork CRD
3032
run: make -C crd/external/podnetwork
3133
- name: Regenerate NodeInfo CRD
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.DEFAULT_GOAL: all
2+
3+
REPO_ROOT = $(shell git rev-parse --show-toplevel)
4+
TOOLS_DIR = $(REPO_ROOT)/build/tools
5+
TOOLS_BIN_DIR = $(REPO_ROOT)/build/tools/bin
6+
CONTROLLER_GEN = $(TOOLS_BIN_DIR)/controller-gen
7+
8+
all: generate manifests
9+
10+
generate: $(CONTROLLER_GEN)
11+
$(CONTROLLER_GEN) object paths="./..."
12+
13+
.PHONY: manifests
14+
manifests: $(CONTROLLER_GEN)
15+
mkdir -p manifests
16+
$(CONTROLLER_GEN) crd paths="./..." output:crd:artifacts:config=manifests/
17+
18+
$(CONTROLLER_GEN):
19+
@make -C $(REPO_ROOT) $(CONTROLLER_GEN)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Pod Network Instance (PNI)
2+
3+
PNIs represent optional requirements, or behavior configurations for how we setup the pod networking. They should map 1:1 and follow the lifetime of a customer workload.
4+
5+
The object points to the PodNetwork for the delegated subnet to use and defines allocation requirements (e.g.: for IPs to reserve for pod endpoints). Orchestrator can map the deployments with these requirements to the PNI object through labels on the pod spec pointing to this object identifier. 
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//go:build !ignore_uncovered
2+
// +build !ignore_uncovered
3+
4+
// Package v1alpha1 contains API Schema definitions for the networking v1alpha1 API group
5+
// +kubebuilder:object:generate=true
6+
// +groupName=acn.azure.com
7+
package v1alpha1
8+
9+
import (
10+
"k8s.io/apimachinery/pkg/runtime/schema"
11+
"sigs.k8s.io/controller-runtime/pkg/scheme"
12+
)
13+
14+
var (
15+
// GroupVersion is group version used to register these objects
16+
GroupVersion = schema.GroupVersion{Group: "acn.azure.com", Version: "v1alpha1"}
17+
18+
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
19+
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
20+
21+
// AddToScheme adds the types in this group-version to the given scheme.
22+
AddToScheme = SchemeBuilder.AddToScheme
23+
)
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//go:build !ignore_uncovered
2+
// +build !ignore_uncovered
3+
4+
package v1alpha1
5+
6+
import (
7+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8+
)
9+
10+
// Important: Run "make" to regenerate code after modifying this file
11+
12+
// +kubebuilder:object:root=true
13+
14+
// PodNetworkInstance is the Schema for the PodNetworkInstances API
15+
// +kubebuilder:resource:scope=Namespaced
16+
// +kubebuilder:resource:shortName=pni
17+
// +kubebuilder:subresource:status
18+
// +kubebuilder:metadata:labels=managed=
19+
// +kubebuilder:metadata:labels=owner=
20+
// +kubebuilder:printcolumn:name="Pod IPs",type=string,priority=1,JSONPath=`.status.podIPAddresses`
21+
// +kubebuilder:printcolumn:name="PodNetwork",type=string,priority=1,JSONPath=`.spec.podNetwork`
22+
// +kubebuilder:printcolumn:name="PodIPReservationSize",type=string,priority=1,JSONPath=`.spec.podIPReservationSize`
23+
type PodNetworkInstance struct {
24+
metav1.TypeMeta `json:",inline"`
25+
metav1.ObjectMeta `json:"metadata,omitempty"`
26+
27+
Spec PodNetworkInstanceSpec `json:"spec,omitempty"`
28+
Status PodNetworkInstanceStatus `json:"status,omitempty"`
29+
}
30+
31+
// +kubebuilder:object:root=true
32+
33+
// PodNetworkInstanceList contains a list of PodNetworkInstance
34+
type PodNetworkInstanceList struct {
35+
metav1.TypeMeta `json:",inline"`
36+
metav1.ListMeta `json:"metadata,omitempty"`
37+
Items []PodNetworkInstance `json:"items"`
38+
}
39+
40+
// PodNetworkInstanceSpec defines the desired state of PodNetworkInstance
41+
type PodNetworkInstanceSpec struct {
42+
// pod network resource object name
43+
PodNetwork string `json:"podnetwork"`
44+
// number of backend IP address to reserve for running pods
45+
// +kubebuilder:default=0
46+
PodIPReservationSize int `json:"podIPReservationSize"`
47+
}
48+
49+
// PodNetworkInstanceStatus defines the observed state of PodNetworkInstance
50+
type PodNetworkInstanceStatus struct {
51+
PodIPAddresses []string `json:"podIPAddresses,omitempty"`
52+
}
53+
54+
func init() {
55+
SchemeBuilder.Register(&PodNetworkInstance{}, &PodNetworkInstanceList{})
56+
}

crd/external/podnetworkinstance/api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 104 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package podnetworkinstance
2+
3+
import (
4+
"context"
5+
"reflect"
6+
7+
"github.com/Azure/azure-container-networking/crd"
8+
"github.com/Azure/azure-container-networking/crd/external/podnetworkinstance/api/v1alpha1"
9+
"github.com/pkg/errors"
10+
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
11+
typedv1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
12+
apierrors "k8s.io/apimachinery/pkg/api/errors"
13+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14+
"k8s.io/apimachinery/pkg/runtime"
15+
"k8s.io/client-go/kubernetes/scheme"
16+
"k8s.io/client-go/rest"
17+
)
18+
19+
// Scheme is a runtime scheme containing the client-go scheme and the PodNetworkInstance scheme.
20+
var Scheme = runtime.NewScheme()
21+
22+
func init() {
23+
_ = scheme.AddToScheme(Scheme)
24+
_ = v1alpha1.AddToScheme(Scheme)
25+
}
26+
27+
// Installer provides methods to manage the lifecycle of the PodNetworkInstance resource definition.
28+
type Installer struct {
29+
cli typedv1.CustomResourceDefinitionInterface
30+
}
31+
32+
func NewInstaller(c *rest.Config) (*Installer, error) {
33+
cli, err := crd.NewCRDClientFromConfig(c)
34+
if err != nil {
35+
return nil, errors.Wrap(err, "failed to init crd client")
36+
}
37+
return &Installer{
38+
cli: cli,
39+
}, nil
40+
}
41+
42+
func (i *Installer) create(ctx context.Context, res *v1.CustomResourceDefinition) (*v1.CustomResourceDefinition, error) {
43+
res, err := i.cli.Create(ctx, res, metav1.CreateOptions{})
44+
if err != nil {
45+
return nil, errors.Wrap(err, "failed to create podnetworkinstance crd")
46+
}
47+
return res, nil
48+
}
49+
50+
// Install installs the embedded PodNetworkInstance CRD definition in the cluster.
51+
func (i *Installer) Install(ctx context.Context) (*v1.CustomResourceDefinition, error) {
52+
podnetworkinstance, err := GetPodNetworkInstances()
53+
if err != nil {
54+
return nil, errors.Wrap(err, "failed to get embedded podnetworkinstance crd")
55+
}
56+
return i.create(ctx, podnetworkinstance)
57+
}
58+
59+
// InstallOrUpdate installs the embedded PodNetworkInstance CRD definition in the cluster or updates it if present.
60+
func (i *Installer) InstallOrUpdate(ctx context.Context) (*v1.CustomResourceDefinition, error) {
61+
podnetworkinstance, err := GetPodNetworkInstances()
62+
if err != nil {
63+
return nil, errors.Wrap(err, "failed to get embedded podnetworkinstance crd")
64+
}
65+
current, err := i.create(ctx, podnetworkinstance)
66+
if !apierrors.IsAlreadyExists(err) {
67+
return current, err
68+
}
69+
if current == nil {
70+
current, err = i.cli.Get(ctx, podnetworkinstance.Name, metav1.GetOptions{})
71+
if err != nil {
72+
return nil, errors.Wrap(err, "failed to get existing podnetworkinstance crd")
73+
}
74+
}
75+
if !reflect.DeepEqual(podnetworkinstance.Spec.Versions, current.Spec.Versions) {
76+
podnetworkinstance.SetResourceVersion(current.GetResourceVersion())
77+
previous := *current
78+
current, err = i.cli.Update(ctx, podnetworkinstance, metav1.UpdateOptions{})
79+
if err != nil {
80+
return &previous, errors.Wrap(err, "failed to update existing podnetworkinstance crd")
81+
}
82+
}
83+
return current, nil
84+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package podnetworkinstance
2+
3+
import (
4+
_ "embed"
5+
6+
"github.com/pkg/errors"
7+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
8+
"sigs.k8s.io/yaml"
9+
)
10+
11+
// PodNetworkInstanceYAML embeds the CRD YAML for downstream consumers.
12+
//
13+
//go:embed manifests/acn.azure.com_podnetworkinstances.yaml
14+
var PodNetworkInstanceYAML []byte
15+
16+
// GetPodNetworkInstances parses the raw []byte PodNetworkInstance in
17+
// to a CustomResourceDefinition and returns it or an unmarshalling error.
18+
func GetPodNetworkInstances() (*apiextensionsv1.CustomResourceDefinition, error) {
19+
podNetworkInstances := &apiextensionsv1.CustomResourceDefinition{}
20+
if err := yaml.Unmarshal(PodNetworkInstanceYAML, &podNetworkInstances); err != nil {
21+
return nil, errors.Wrap(err, "error unmarshalling embedded podNetworkInstance")
22+
}
23+
return podNetworkInstances, nil
24+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package podnetworkinstance
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
const filename = "manifests/acn.azure.com_podnetworkinstances.yaml"
11+
12+
func TestEmbed(t *testing.T) {
13+
b, err := os.ReadFile(filename)
14+
assert.NoError(t, err)
15+
assert.Equal(t, b, PodNetworkInstanceYAML)
16+
}
17+
18+
func TestGetPodNetworkInstances(t *testing.T) {
19+
_, err := GetPodNetworkInstances()
20+
assert.NoError(t, err)
21+
}

0 commit comments

Comments
 (0)