Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correcting identifiers #179

Merged
merged 6 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .linkspector.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ ignorePatterns:
- pattern: "^http://localhost.*$"
- pattern: "^http://HOSTNAME:PORT.*$"
- pattern: "172\\.18\\.255\\.200"
- pattern: "https://\\*kpt\\*\\.dev/"
- pattern: "https://my-gitlab\\.com/joe\\.bloggs/blueprints\\.git"
- pattern: "http://172\\.18\\.0\\.200:3000/nephio/"
replacementPatterns:
- pattern: ".md#.*$"
replacement: ".md"
1 change: 1 addition & 0 deletions content/en/docs/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,4 @@ demonstration purposes, the same principles and code can be used for managing
other infrastructure and network functions. The *uniformity in systems*
principle means that as long as something is manageable via the Kubernetes
Resource Model, it is manageable via Nephio.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ weight: 1
The [Helm to Operator Codegen SDK](https://github.com/nephio-project/nephio-sdk/tree/main/helm-to-operator-codegen-sdk) offers a streamlined solution for translating existing Helm charts into Kubernetes operators with minimal effort and cost.

## The Flow Diagram
In a nutshell, the Helm-Charts are converted to YAML files using the values provided in "values.yaml". Then, each Kubernetes Resource Model (KRM) in the YAML is translated into Go code, employing one of two methods.
In a nutshell, the Helm-Charts are converted to YAML files using the values provided in *values.yaml*. Then, each Kubernetes Resource Model (KRM) in the YAML is translated into Go code, employing one of two methods.
1) If the resource is Runtime-Supported, it undergoes a conversion process where the KRM resource is first transformed into a Runtime Object, then into JSON, and finally into Go code.
2) Otherwise, if the resource is not Runtime-Supported, it is converted into an Unstructured Object and then into Go code.

Expand All @@ -20,7 +20,7 @@ Helm to YAML conversion is achieved by running the following command
`helm template <chart> --namespace <namespace> --output-dir “temp/templated/”` internally. As of now, it retrieves the values from default "values.yaml"

### Flow-2: YAML Split
The SDK iterates over each YAML file in the "converted-yamls" directory. If a YAML file contains multiple Kubernetes Resource Models (KRM), separated by "---", the SDK splits the YAML file accordingly to isolate each individual KRM resource. This ensures that each KRM resource is processed independently.
The SDK iterates over each YAML file in the *converted-yamls* directory. If a .yaml file contains multiple Kubernetes Resource Models (KRM), separated by "---", the SDK splits the .yaml file accordingly to isolate each individual KRM resource. This ensures that each KRM resource is processed independently.

### Runtime-Object and Unstruct-Object
The SDK currently employs the "runtime-object method" to handle Kubernetes resources whose structure is recognized by Kubernetes by default. Examples of such resources include Deployment, Service, and ConfigMap. Conversely, resources that are not inherently known to Kubernetes and require explicit installation or definition, such as Third-Party Custom Resource Definitions (CRDs) like NetworkAttachmentDefinition or PrometheusRule, are processed using the "unstructured-object" method. Such examples are given below:
Expand Down Expand Up @@ -69,15 +69,14 @@ networkAttachmentDefinition1 := &unstructured.Unstructured{
```

### Flow-3.1: KRM to Runtime-Object
The conversion process relies on the "k8s.io/apimachinery/pkg/runtime" package. Currently, only the API version "v1" is supported. The supported kinds for the Runtime Object method include:
`Deployment, Service, Secret, Role, RoleBinding, ClusterRoleBinding, PersistentVolumeClaim, StatefulSet, ServiceAccount, ClusterRole, PriorityClass, ConfigMap`
The conversion process relies on the "k8s.io/apimachinery/pkg/runtime" package. Currently, only the API version "v1" is supported. The supported kinds for the Runtime Object method include: Deployment, Service, Secret, Role, RoleBinding, ClusterRoleBinding, PersistentVolumeClaim, StatefulSet, ServiceAccount, ClusterRole, PriorityClass, ConfigMap

### Flow-3.2: Runtime-Object to JSON
Firstly, the SDK performs a typecast of the runtime object to its actual data type. For instance, if the Kubernetes Kind is "Service," the SDK typecasts the runtime object to the specific data type corev1.Service. Then, it conducts a Depth-First Search (DFS) traversal over the corev1.Service object using reflection. During this traversal, the SDK generates a JSON structure that encapsulates information about the struct hierarchy, including corresponding data types and values. This transformation results in a JSON representation of the corev1.Service object's structure and content.

#### DFS Algorithm Cases

The DFS function iterates over the runtime object, traversing its structure in a Depth-First Search manner. During this traversal, it constructs the JSON structure while inspecting each attribute for its data type and value. Attributes that have default values in the runtime object but are not explicitly set in the YAML file are omitted from the conversion process. This ensures that only explicitly defined attributes with their corresponding values are included in the resulting JSON structure. The function follows this flow to accurately capture the structure, data types, and values of the Kubernetes resource while excluding default attributes that are not explicitly configured in the YAML file.
The DFS function iterates over the runtime object, traversing its structure in a Depth-First Search manner. During this traversal, it constructs the JSON structure while inspecting each attribute for its data type and value. Attributes that have default values in the runtime object but are not explicitly set in the .yaml file are omitted from the conversion process. This ensures that only explicitly defined attributes with their corresponding values are included in the resulting JSON structure. The function follows this flow to accurately capture the structure, data types, and values of the Kubernetes resource while excluding default attributes that are not explicitly configured in the .yaml file.


A) Base-Cases:
Expand Down Expand Up @@ -156,7 +155,7 @@ spec:
```

### Flow-3.3: JSON to String (Go-Code)
The SDK reads the JSON file containing the information about the Kubernetes resource and then translates this information into a string of Go code. This process involves parsing the JSON structure and generating corresponding Go code strings based on the structure, data types, and values extracted from the JSON representation. Ultimately, this results in a string that represents the Kubernetes resource in a format compatible with Go code.
The SDK reads the .json file containing the information about the Kubernetes resource and then translates this information into a string of Go code. This process involves parsing the JSON structure and generating corresponding Go code strings based on the structure, data types, and values extracted from the JSON representation. Ultimately, this results in a string that represents the Kubernetes resource in a format compatible with Go code.

#### TraverseJSON Cases (Json-to-String)
The traverse JSON function is responsible for converting JSON data into Go code. Here's how it handles base cases:
Expand Down Expand Up @@ -275,12 +274,12 @@ Structs need to be initialized using curly brackets {}, whereas enums need Paren

Solution: We solve the above problems by building an “enumModuleMapping” which is a set that stores all data types that are enums. i.e. If a data type belongs to the set, then It is an Enum.

There is an automation-script that takes the types.go files of packages and build the config-json. For details, Please refer [here](https://github.com/nephio-project/nephio-sdk/tree/main/helm-to-operator-codegen-sdk/config)
There is an automation-script that takes the *types.go* files of packages and build the config-json. For details, Please refer [here](https://github.com/nephio-project/nephio-sdk/tree/main/helm-to-operator-codegen-sdk/config)


### Flow-4: KRM to Unstruct-Obj to String(Go-code)
All Kubernetes resource kinds that are not supported by the runtime-object method are handled using the unstructured method. In this approach, the Kubernetes Resource MOdel (KRM) is converted to an unstructured object using the package "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured".
Then, We traverse the unstructured-Obj in a DFS fashion and build the gocode-string.
All Kubernetes resource kinds that are not supported by the runtime-object method are handled using the unstructured method. In this approach, the Kubernetes Resource MOdel (KRM) is converted to an unstructured object using the package *k8s.io/apimachinery/pkg/apis/meta/v1/unstructured*"*.
Then, we traverse the unstructured-Obj in a DFS fashion and build the gocode-string.


#### DFS Algorithm Cases (Unstruct-Version)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,11 @@ Connecting to Gitea allows you to see the actions that Nephio takes on Gitea.
kubectl port-forward -n gitea svc/gitea 3000:3000
```

2. Browse to the Gitea web client at `http://localhost:3000` and log on.
2. Browse to the Gitea web client at http://localhost:3000 and log on.

## VS Code Configuration

Set up a launch configuration in VS Code `launch.json` similar to the configuration below:
Set up a launch configuration in VS Code *launch.json* similar to the configuration below:

```json
{
Expand Down
34 changes: 17 additions & 17 deletions content/en/docs/guides/contributor-guides/unit-testing-mockery.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ This guide will help folks come up to speed on using testify and mockery.

## How Mockery works

The [mockery documentation](https://vektra.github.io/mockery/latest/#why-mockery) describes why you would use and how to use Mockery. In a nutshell, Mockery generates mock implementations for interfaces in `go`, which you can then use instead of real implementations when unit testing.
The [mockery documentation](https://vektra.github.io/mockery/latest/#why-mockery) describes why you would use and how to use Mockery. In a nutshell, Mockery generates mock implementations for interfaces in go, which you can then use instead of real implementations when unit testing.

## Mockery support in Nephio `make`

The `make` files in Nephio repos containing `go` code have targets to support mockery.
The `make` files in Nephio repos containing go code have targets to support mockery.

The [default-mockery.mk](https://github.com/nephio-project/nephio/blob/main/default-mockery.mk) file in the root of Nephio repos is included in Nephio `make` runs.

Expand All @@ -27,13 +27,13 @@ The targets above must be run explicitly.

Run `make install-mockery` to install mockery in your container runtime (docker, podman etc) or locally if you have no container runtime running. You need only run this target once unless you need to reinstall Mockery for whatever reason.

Run `make generate-mocks` to generate the mocked implementation of the go interfaces specified in '.mockery.yaml' files. You need to run this target each time an interface that you are mocking changes or whenever you change the contents of a `.mockery.yaml` file. You can run `make generate-mocks` in the repo root to generate or re-generate all interfaces or in subdirectories containing a `Makefile` to generate or regenerate only the interfaces in that subdirectory and its children.
Run `make generate-mocks` to generate the mocked implementation of the go interfaces specified in *.mockery.yaml* files. You need to run this target each time an interface that you are mocking changes or whenever you change the contents of a *.mockery.yaml* file. You can run `make generate-mocks` in the repo root to generate or re-generate all interfaces or in subdirectories containing a Makefile to generate or regenerate only the interfaces in that subdirectory and its children.

The generate-mocks target looks for `.mockery.yaml` files in the repo and it runs the mockery mock generator on each `.mockery.yaml` file it finds. This has the nice effect of allowing `.mockery.yaml` files to be in either the root of the repo or in subdirectories, so the choice of placement of `.mockery.yaml` files is left to the developer.
The generate-mocks target looks for *.mockery.yaml`* files in the repo and it runs the mockery mock generator on each *.mockery.yaml* file it finds. This has the nice effect of allowing *.mockery.yaml* files to be in either the root of the repo or in subdirectories, so the choice of placement of *.mockery.yaml* files is left to the developer.

## The .mockery.yaml file

The `.mockery.yaml` file specifies which mock implementations Mockery should generate and also controls how that generation is performed. Here we just give an overview of `mockery.yaml`. For full details consult the [configuration](https://github.com/vektra/mockery/blob/master/docs/configuration.md) section of the Mockery documentation.
The *.mockery.yaml* file specifies which mock implementations Mockery should generate and also controls how that generation is performed. Here we just give an overview of *mockery.yaml*. For full details consult the [configuration](https://github.com/vektra/mockery/blob/master/docs/configuration.md) section of the Mockery documentation.

### Example 1

Expand All @@ -53,7 +53,7 @@ We provide a list of the packages for which we want to generate mocks. In this e
6. dir: "{{.InterfaceDir}}"
```

We want mocks to be generated for the `GiteaClient` go interface (line 4). The `{{.InterfaceDir}}` parameter (line 6) asks Mockery to generate the mock file in the same directory as the interface is located.
We want mocks to be generated for the GiteaClient go interface (line 4). The {{.InterfaceDir}} parameter (line 6) asks Mockery to generate the mock file in the same directory as the interface is located.

### Example 2

Expand All @@ -80,22 +80,22 @@ Lines 2 to 7 are as explained in Example 1 above.
8. sigs.k8s.io/controller-runtime/pkg/client:
```

Generate mocks for the external package `sigs.k8s.io/controller-runtime/pkg/client`.
Generate mocks for the external package *sigs.k8s.io/controller-runtime/pkg/client*.

```
9. interfaces:
10. Client:
```

Generate a mock implementation of the go interface `Client` in the external package `sigs.k8s.io/controller-runtime/pkg/client`.
Generate a mock implementation of the go interface Client in the external package *sigs.k8s.io/controller-runtime/pkg/client*.

```
11. config:
12. dir: "mocks/external/{{ .InterfaceName | lower }}"
13. outpkg: "mocks"
```

Create the mocks for the `Client` interface in the `mocks/external/client` directory and cal the output package `mocks`.
Create the mocks for the Client interface in the *mocks/external/client* directory and cal the output package *mocks*.

## The generated mock implementation

Expand All @@ -107,7 +107,7 @@ We can treat this generated file as a black box and we do not have to know the d

The [mockery utils](https://github.com/nephio-project/nephio/tree/main/testing/mockeryutils) package is a utility package that you can use to initialize your mocks and to define some common fields for your tests.

[mockeryutils-types.go](https://github.com/nephio-project/nephio/blob/main/testing/mockeryutils/mockeryutils-types.go) contains the `MockHelper` struct, which allows you to control the behaviour of a mock.
[mockeryutils-types.go](https://github.com/nephio-project/nephio/blob/main/testing/mockeryutils/mockeryutils-types.go) contains the MockHelper struct, which allows you to control the behaviour of a mock.

```
type MockHelper struct {
Expand All @@ -117,15 +117,15 @@ type MockHelper struct {
}
```

The `MockHelper` struct is used to configure a mocked method to expect and return a certain set of arguments. We pass instances of this struct to the mocked interface during tests.
The MockHelper struct is used to configure a mocked method to expect and return a certain set of arguments. We pass instances of this struct to the mocked interface during tests.

[mockeryutils.go](https://github.com/nephio-project/nephio/blob/main/testing/mockeryutils/mockeryutils-types.go) contains the `InitMocks` function, which initializes your mocks for you before a test.
[mockeryutils.go](https://github.com/nephio-project/nephio/blob/main/testing/mockeryutils/mockeryutils-types.go) contains the InitMocks function, which initializes your mocks for you before a test.

```
func InitMocks(mocked *mock.Mock, mocks []MockHelper)
```

For the given `mocked` interface, the function initializes the `mocks` as specified in the given `MockHelper` array.
For the given mocked interface, the function initializes the mocks as specified in the given MockHelper array.

## Using the mock implementation in unit tests

Expand All @@ -151,7 +151,7 @@ type repoTest struct {
wantErr bool
}
```
The code above allows us to specify input data and the expected outcome for tests. Each test is specified as an instance of the `repoTest` struct. For each test, we specify its fields and arguments, and specify the mocking for the test.
The code above allows us to specify input data and the expected outcome for tests. Each test is specified as an instance of the repoTest struct. For each test, we specify its fields and arguments, and specify the mocking for the test.

```
func TestUpsertRepo(t *testing.T)
Expand Down Expand Up @@ -194,7 +194,7 @@ This is the specification of an array of tests that we will run.
}
```

The code above specifies a single test and is an instance of the `tests` array. We specify the fields, arguments, and mocks for the test. In this case, we mock three functions on our GiteaClient interface: `GetMyUserInfo`, `GetRepo`, and `CreateRepo`. We specify the arguments we expect for each function and specify what the function should return if it receives correct arguments. Of course, if the mocked function receives incorrect arguments, it will report an error. The `wantErr` value indicates if we expect the `upsertRepo` function being tested to succeed or fail.
The code above specifies a single test and is an instance of the tests array. We specify the fields, arguments, and mocks for the test. In this case, we mock three functions on our GiteaClient interface: GetMyUserInfo, GetRepo, and CreateRepo. We specify the arguments we expect for each function and specify what the function should return if it receives correct arguments. Of course, if the mocked function receives incorrect arguments, it will report an error. The wantErr value indicates if we expect the upsertRepo function being tested to succeed or fail.

```
for _, tt := range tests {
Expand All @@ -214,7 +214,7 @@ for _, tt := range tests {
}
```

The code above executes the tests. We run a reconciler `r` and initialize our tests using the local `initMockeryTests()` function. We then call the `upsertRepo` function to test it and check the result.
The code above executes the tests. We run a reconciler `r` and initialize our tests using the local initMockeryTests() function. We then call the upsertRepo function to test it and check the result.

```
func initMockeryMocks(tt *repoTest) {
Expand All @@ -225,4 +225,4 @@ func initMockeryMocks(tt *repoTest) {
}
```

The `initMockeryMocks` local function calls the `mockeryutils.InitMocks` to initialize the mocks for the tests.
The initMockeryMocks local function calls the mockeryutils.InitMocks to initialize the mocks for the tests.
Loading
Loading