Skip to content

Commit

Permalink
Merge pull request #1 from jain-ashish-sam/main
Browse files Browse the repository at this point in the history
Intial Seed Code for helm-to-operator-codegen-sdk (#415)
  • Loading branch information
tliron authored Jan 31, 2024
2 parents 71e09ee + f23b66f commit 95531c8
Show file tree
Hide file tree
Showing 44 changed files with 3,768 additions and 2 deletions.
2 changes: 0 additions & 2 deletions README.md

This file was deleted.

4 changes: 4 additions & 0 deletions helm-to-operator-codegen-sdk/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
testing_helpers
outputs/generated_code.go
temp
experiments
71 changes: 71 additions & 0 deletions helm-to-operator-codegen-sdk/.prow.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
presubmits:
- name: presubmit-api-go-test-sdk
decorate: true
run_if_changed: "^.*.go$"
spec:
containers:
- image: nephio/gotests:7
command:
- make
args:
- unit
- name: presubmit-api-gosec-sdk
decorate: true
run_if_changed: "^.*.go$"
spec:
containers:
- image: nephio/gotests:7
command:
- make
args:
- gosec
- name: presubmit-api-golangci-lint-sdk
decorate: true
run_if_changed: "^.*.go$"
spec:
containers:
- image: nephio/gotests:7
command:
- make
args:
- lint
- name: presubmit-api-license-header-check-sdk
decorate: true
run_if_changed: "^.*.go$"
spec:
containers:
- image: nephio/gotests:7
command:
- "/bin/sh"
- "-c"
- |
/usr/local/bin/checklicense.sh > ${ARTIFACTS}/license_headers_results.txt
- name: presubmit-api-scancode-toolkit-sdk
decorate: true
always_run: true
spec:
containers:
- image: nephio/scancode-toolkit:v31.2.5
command:
- "/bin/sh"
args:
- "-c"
- |
/scancode-toolkit/scancode --ignore "whitelist.json" -clpeui -n 2 --html ${ARTIFACTS}/scancode_report.html . --tallies-with-details
resources:
requests:
cpu: 2
memory: 1Gi
- name: presubmit-api-fossology-sdk
decorate: true
always_run: true
spec:
containers:
- image: fossology/fossology:scanner
command:
- "/bin/bash"
args:
- "-c"
- |
/bin/fossologyscanner --report SPDX_JSON repo nomos ojo copyright keyword
cp -R results ${ARTIFACTS}/
File renamed without changes.
88 changes: 88 additions & 0 deletions helm-to-operator-codegen-sdk/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
GO_VERSION ?= 1.20.2
GOLANG_CI_VER ?= v1.52
GOSEC_VER ?= 2.15.0
TEST_COVERAGE_FILE=lcov.info
TEST_COVERAGE_HTML_FILE=coverage_unit.html
TEST_COVERAGE_FUNC_FILE=func_coverage.out

# CONTAINER_RUNNABLE checks if tests and lint check can be run inside container.
PODMAN ?= $(shell podman -v > /dev/null 2>&1; echo $$?)
ifeq ($(PODMAN), 0)
CONTAINER_RUNTIME=podman
else
CONTAINER_RUNTIME=docker
endif
CONTAINER_RUNNABLE ?= $(shell $(CONTAINER_RUNTIME) -v > /dev/null 2>&1; echo $$?)

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
else
GOBIN=$(shell go env GOBIN)
endif

# Setting SHELL to bash allows bash commands to be executed by recipes.
# This is a requirement for 'setup-envtest.sh' in the test target.
# Options are set to exit when a recipe line exits non-zero or a piped command fails.
SHELL = /usr/bin/env bash -o pipefail
.SHELLFLAGS = -ec

##@ General

# The help target prints out all targets with their descriptions organized
# beneath their categories. The categories are represented by '##@' and the
# target descriptions by '##'. The awk commands is responsible for reading the
# entire set of makefiles included in this invocation, looking for lines of the
# file as xyz: ## something, and then pretty-format the target and help. Then,
# if there's a line with ##@ something, that gets pretty-printed as a category.
# More info on the usage of ANSI control characters for terminal formatting:
# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters
# More info on the awk command:
# http://linuxcommand.org/lc3_adv_awk.php

.PHONY: help
help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)


.PHONY: unit_clean
unit_clean: ## clean up the unit test artifacts created
ifeq ($(CONTAINER_RUNNABLE), 0)
$(CONTAINER_RUNTIME) system prune -f
endif
rm -f ${TEST_COVERAGE_FILE} ${TEST_COVERAGE_HTML_FILE} ${TEST_COVERAGE_FUNC_FILE}

.PHONY: unit
unit: ## Run unit tests against code. Installing Helm also as a pre-requisite
ifeq ($(CONTAINER_RUNNABLE), 0)
$(CONTAINER_RUNTIME) run -it -v ${PWD}:/go/src -w /go/src docker.io/library/golang:${GO_VERSION}-alpine3.17 \
/bin/sh -c "wget https://get.helm.sh/helm-v3.9.3-linux-amd64.tar.gz; \
tar xvf helm-v3.9.3-linux-amd64.tar.gz; \
mv linux-amd64/helm /usr/local/bin; \
rm -rf linux-amd64 helm-v3.9.3-linux-amd64.tar.gz; \
go test ./... -v -coverprofile ${TEST_COVERAGE_FILE}; \
go tool cover -html=${TEST_COVERAGE_FILE} -o ${TEST_COVERAGE_HTML_FILE}; \
go tool cover -func=${TEST_COVERAGE_FILE} -o ${TEST_COVERAGE_FUNC_FILE}"
else
go test ./... -v -coverprofile ${TEST_COVERAGE_FILE}
go tool cover -html=${TEST_COVERAGE_FILE} -o ${TEST_COVERAGE_HTML_FILE}
go tool cover -func=${TEST_COVERAGE_FILE} -o ${TEST_COVERAGE_FUNC_FILE}
endif

# Install link at https://golangci-lint.run/usage/install/ if not running inside a container
.PHONY: lint
lint: ## Run lint against code.
ifeq ($(CONTAINER_RUNNABLE), 0)
$(CONTAINER_RUNTIME) run -it -v ${PWD}:/go/src -w /go/src docker.io/golangci/golangci-lint:${GOLANG_CI_VER}-alpine golangci-lint run ./... -v
else
golangci-lint run ./... -v --timeout 10m
endif

# Install link at https://github.com/securego/gosec#install if not running inside a container
.PHONY: gosec
gosec: ## inspects source code for security problem by scanning the Go Abstract Syntax Tree
ifeq ($(CONTAINER_RUNNABLE), 0)
$(CONTAINER_RUNTIME) run -it -v ${PWD}:/go/src -w /go/src docker.io/securego/gosec:${GOSEC_VER} ./...
else
gosec ./...
endif
76 changes: 76 additions & 0 deletions helm-to-operator-codegen-sdk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Helm to Operator Codegen Sdk
The "Helm to Operator Codegen Sdk" takes the helm chart as input and generates the golang-code which can be used by kubernetes operator to create/delete all the resources previously managed by the helm charts. The sdk can be employed to transition from helm-way-of-deploying-resources to the operator way.

Note: It is currently an experimental feature.

### Step 0: Prerequisite
1. GoLang Version: 1.21
2. Helm : v3.9.3
3. Go Packages:
```
# Clone the Repo
cd nephio-sdk/helm-to-operator-codegen-sdk/
go mod tidy
```

### Step 1: Running the sdk
```
go run main.go <path_to_local_helm_chart> <namespace> <logging-level>
```
Note:
1. The logging-level can be set to one of the following values: debug, info (default), error, warn
2. If <path_to_local_helm_chart> is not provided, then by default it would take the helm_charts present in Input-folder.

#### Example Run
```
go run main.go /home/ubuntu/free5gccharts/towards5gs-helm/charts/free5gc/charts/free5gc-amf/ free5gcns info
```
<details>
<summary>The output is similar to:</summary>

```console
INFO[0000] ----------------- Converting Helm to Yaml --------------------------
WARN[0000] Duplication Detected in Struct Mapping | For Preconditions
WARN[0000] Duplication Detected in Struct Mapping | For ConditionStatus
WARN[0000] Duplication Detected in Enum Mapping | For ConditionStatus
INFO[0000] CurFile --> | temp/templated/free5gc-amf/templates/amf-configmap.yaml
INFO[0000] Current KRM Resource| Kind : ConfigMap| YamlFilePath : temp/templated/free5gc-amf/templates/amf-configmap.yaml
INFO[0000] Converting Runtime to Json Completed
INFO[0000] Converting Json to String Completed
INFO[0000] CurFile --> | temp/templated/free5gc-amf/templates/amf-deployment.yaml
INFO[0000] Current KRM Resource| Kind : Deployment| YamlFilePath : temp/templated/free5gc-amf/templates/amf-deployment.yaml
INFO[0000] Converting Runtime to Json Completed
INFO[0000] Converting Json to String Completed
INFO[0000] CurFile --> | temp/templated/free5gc-amf/templates/amf-hpa.yaml
ERRO[0000] Unable to convert yaml to unstructured |Object 'Kind' is missing in 'null'
INFO[0000] CurFile --> | temp/templated/free5gc-amf/templates/amf-ingress.yaml
ERRO[0000] Unable to convert yaml to unstructured |Object 'Kind' is missing in 'null'
INFO[0000] CurFile --> | temp/templated/free5gc-amf/templates/amf-n2-nad.yaml
INFO[0000] Kind | NetworkAttachmentDefinition Would Be Treated as Third Party Kind
INFO[0000] Converting Unstructured to String Completed
INFO[0000] CurFile --> | temp/templated/free5gc-amf/templates/amf-service.yaml
INFO[0000] Current KRM Resource| Kind : Service| YamlFilePath : temp/templated/free5gc-amf/templates/amf-service.yaml
INFO[0000] Converting Runtime to Json Completed
INFO[0000] Converting Json to String Completed
INFO[0000] ----------------- Writing GO Code ---------------------------------
INFO[0000] ----------------- Program Run Successful| Summary ---------------------------------
INFO[0000] Deployment |1
INFO[0000] NetworkAttachmentDefinition |1
INFO[0000] Service |1
INFO[0000] ConfigMap |1
```
</details>


The generated Go-Code would be written to the "outputs/generated_code.go" file

The Generated Go-Code shall contain the following plugable functions:
1. Create_All(): When called, it will create all the k8s resources(services, deployment) on the kubernetes cluster.
2. Delete_All(): When called, it will delete all the k8s resources(services, deployment) on the kubernetes cluster.
3. Get_Resources(): Shall return the list of a particular resource.
1. Get_Service(): Shall return the list of all services.
2. Get_Deployment(): Shall return the list of all deployments. & so on

Further Docs:
1. Design Document: [link](https://docs.google.com/document/d/1b7WpK_BHe7nRuGP5MOy6Mxf3hpN_cro9/edit)
2. Detailed Algorithm: [link](https://1drv.ms/p/s!AkgeY1fT2A5UhQK4IWBxOJ6YUerh?e=BmBkRc)
1 change: 1 addition & 0 deletions helm-to-operator-codegen-sdk/common/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# helm-operatort-sdk
61 changes: 61 additions & 0 deletions helm-to-operator-codegen-sdk/common/helm_to_yaml.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
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 common

import (
"bufio"
"fmt"
"os/exec"

"github.com/sirupsen/logrus"
)

type HelmYamlConvertor struct {
Namespace string
Chartpath string
}

/*
Converts the Helm-Chart to Yaml Template in temp folder,
Runs the bash command "helm template <chartpath> --namespace <namespace> --output-dir temp/templated/"
Todo: Increase the functionality to handle remote helm charts, and support for using different values.yaml & so on
*/
func (obj *HelmYamlConvertor) ConvertHelmToYaml() error {
logrus.Info(obj.Namespace, " ", obj.Chartpath)
logrus.Info(" ----------------- Converting Helm to Yaml --------------------------")
_ = createDirIfDontExist("temp")
if obj.Namespace == "" {
obj.Namespace = "default"
}
cmdStruct := exec.Command("helm", "template", obj.Chartpath, "--namespace", obj.Namespace, "--output-dir", "temp/templated/") // #nosec G204
stderr, _ := cmdStruct.StderrPipe() // Intialising a Pipe to read error stream
if err := cmdStruct.Start(); err != nil {
logrus.Error(err)
return err
}

scanner := bufio.NewScanner(stderr)
helmCmdErr := ""
for scanner.Scan() {
helmCmdErr += scanner.Text()
}
if len(helmCmdErr) > 0 {
logrus.Error("Error while running the command| helm template " + obj.Chartpath + " --namespace " + obj.Namespace + " --output-dir temp/templated/ ")
return fmt.Errorf(helmCmdErr)
}
return nil
}
31 changes: 31 additions & 0 deletions helm-to-operator-codegen-sdk/common/helm_to_yaml_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
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 common

import (
"os"
"testing"
)

func TestConvertHelmToYaml(t *testing.T) {
var helmYamlConvertor = HelmYamlConvertor{Namespace: "myns", Chartpath: "tests/test-helmCharts/hello-world/"}
err := helmYamlConvertor.ConvertHelmToYaml()
if err != nil {
t.Errorf("Unable to convert helm-chart to yamls using helm template | Error %v", err)
}
os.RemoveAll("temp")
}
Loading

0 comments on commit 95531c8

Please sign in to comment.