From: Vamshi Namilikonda Date: Wed, 19 Jun 2024 08:47:48 +0000 (+0530) Subject: helm application re-alignment. X-Git-Tag: l-release~10 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F50%2F12850%2F12;p=smo%2Fo2.git helm application re-alignment. Issue-ID: SMO-145 Change-Id: I41b1fb72571a7ed1d77eec3e356b27a2acae98cf Signed-off-by: Vamshi Namilikonda adding package variant files Issue-ID: SMO-145 Change-Id: I41b1fb72571a7ed1d77eec3e356b27a2acae98cf Signed-off-by: Vamshi Namilikonda Remove __pycache__ directories Issue-ID: SMO-145 Change-Id: I41b1fb72571a7ed1d77eec3e356b27a2acae98cf Signed-off-by: Vamshi Namilikonda --- diff --git a/nfo/k8s/examples/clients/python_helm_client.py b/nfo/k8s/examples/clients/python_helm_client.py new file mode 100644 index 0000000..9d58598 --- /dev/null +++ b/nfo/k8s/examples/clients/python_helm_client.py @@ -0,0 +1,92 @@ +#https://github.com/stackhpc/pyhelm3 + +import requests +from pyhelm3 import Client +import asyncio + +async def test_client(): + #endpoint = "https://httpbin.org/get" + endpoint = "http://127.0.0.1:8000/api/" + getresponse = requests.get(endpoint, json={"query":"Hello, World!"}) + + #print(getresponse.text) + print(getresponse.status_code) + #print(getresponse.json()['message']) + print(getresponse.json()) + +async def get_current_version(): + client = Client() + client = Client(kubeconfig = "/home/fnclab/.kube/config") + client = Client(executable = "/usr/local/bin/helm") + # Get the current revision for an existing release + revision = await client.get_current_revision("hello-world-1711020846", namespace = "default") + chart_metadata = await revision.chart_metadata() + print( + revision.release.name, + revision.release.namespace, + revision.revision, + str(revision.status), + chart_metadata.name, + chart_metadata.version + ) + +async def list_releases(): + client = Client() + client = Client(kubeconfig = "/home/fnclab/.kube/config") + client = Client(executable = "/usr/local/bin/helm") + + # List the deployed releases + releases = await client.list_releases(all = True, all_namespaces = True) + for release in releases: + print("executing for loop ->") + revision = await release.current_revision() + print(release.name, release.namespace, revision.revision, str(revision.status)) + +async def uninstall_helm(): + client = Client() + client = Client(kubeconfig = "/home/fnclab/.kube/config") + client = Client(executable = "/usr/local/bin/helm") + revision = await client.get_current_revision("cert-manager", namespace = "default") + await revision.release.uninstall(wait = True) + # Or directly by name + await client.uninstall_release("cert-manager", namespace = "default", wait = True) + +async def install_helm(): + print("executing test_helmClient() ->") + + # This will use the Kubernetes configuration from the environment + client = Client() + # Specify the kubeconfig file to use + client = Client(kubeconfig = "/home/fnclab/.kube/config") + # Specify a custom Helm executable (by default, we expect 'helm' to be on the PATH) + client = Client(executable = "/usr/local/bin/helm") + + # Fetch a chart + chart = await client.get_chart( + "cert-manager", + repo = "https://charts.jetstack.io", + version = "v1.8.x" + ) + print(chart.metadata.name, chart.metadata.version) + #print(await chart.readme()) + + # Install or upgrade a release + revision = await client.install_or_upgrade_release( + "cert-manager", + chart, + { "installCRDs": True }, + atomic = True, + wait = True + ) + print( + revision.release.name, + revision.release.namespace, + revision.revision, + str(revision.status) + ) + +if __name__ == "__main__": + #asyncio.run(get_current_version()) + #asyncio.run(list_releases()) + #asyncio.run(install_helm()) + asyncio.run(uninstall_helm()) diff --git a/nfo/k8s/examples/clients/python_k8s_client.py b/nfo/k8s/examples/clients/python_k8s_client.py new file mode 100644 index 0000000..a43ed24 --- /dev/null +++ b/nfo/k8s/examples/clients/python_k8s_client.py @@ -0,0 +1,181 @@ +import kubernetes +from kubernetes import client, config, utils +import requests +import yaml +from kubernetes.dynamic import DynamicClient +import json +import yaml + +def main(): + #get_remote_file() + + #config.load_kube_config() + #k8s_client = client.ApiClient() + #aml_file = 'nginx.yaml' + #yaml_file = 'nginx-deployment.yaml' + #print (yaml_file) + + #create_native_resource(yaml_file) + #delete_native_resource(yaml_file) + #get_native_resource(yaml_file) + + create_custom_resource() + #get_custom_resource() + #delete_custom_resource("config.porch.kpt.dev", "v1alpha1", "default", "packagevariants", "edge-oai-cuup-test") + + #utils.delete_from_yaml(k8s_client, yaml_file) + +def create_native_resource(yaml_file): + print ("--- Creating Kubernetes native resource ---") + config.load_kube_config() + k8s_client = client.ApiClient() + utils.create_from_yaml(k8s_client, yaml_file) + +def create_custom_resource(): + # Load kube config + #config.load_kube_config() + config.load_kube_config(config_file='/home/ubuntu/.kube/config') + + # Create a dynamic client + dyn_client = DynamicClient(client.ApiClient()) + + with open("oai/oai-cuup.yaml", "r") as stream: + custom_resource = yaml.safe_load(stream) + print (custom_resource) + + # Create the custom resource using the dynamic client + my_resource = dyn_client.resources.get(api_version='config.porch.kpt.dev/v1alpha1', kind='PackageVariant') + created_resource = my_resource.create(body=custom_resource, namespace='default') + print("created_resource before yaml.safe_load():", created_resource) + + yaml_data = created_resource.to_yaml() + # Parse the YAML content into a Python dictionary + data = yaml.safe_load(yaml_data) + + # Convert the Python dictionary to a JSON string + json_str = json.dumps(data, indent=2) + print(json_str) + + print(f"Created resource mycrd") + + ''' # Create a CustomObjectsAPI instance + custom_api = client.CustomObjectsApi() + custom_api.create_cluster_custom_object(group=group, version=version, plural=plural, body=custom_resource) ''' + +def delete_custom_resource(group, version, namespace, plural, name): + # Load kube config + #config.load_kube_config() + config.load_kube_config(config_file='/home/ubuntu/.kube/config') + + # Create a CustomObjectsAPI instance + custom_api = client.CustomObjectsApi() + + # Delete the custom resource + custom_api.delete_namespaced_custom_object( + group=group, + version=version, + namespace=namespace, + plural=plural, + name=name + ) + + print("********** Delted *********") + +def delete_native_resource(yaml_file): + # Load kube config + config.load_kube_config() + + # Create API client + api_client = client.ApiClient() + + # Create a Kubernetes object from the YAML file + #k8s_obj = utils.create_from_yaml(api_client, yaml_file) + + with open(yaml_file, "r") as f: + k8s_obj = yaml.load(f, Loader=yaml.FullLoader) + print(k8s_obj) + + # Get the kind of the object (e.g., Pod, Service, etc.) + kind = k8s_obj["kind"] + + # Get the metadata of the object + metadata = k8s_obj["metadata"] + + # Create a delete options object + delete_options = client.V1DeleteOptions() + + if kind == "Pod": + v1 = client.CoreV1Api(api_client) + v1.delete_namespaced_pod(metadata["name"], metadata["namespace"], body=delete_options) + + #elif kind == "Deployment": + #v1 = client.CoreV1Api(api_client) + #v1.delete_namespaced_deployment(metadata["name"], metadata["namespace"], body=delete_options) + + elif kind == "Service": + v1 = client.CoreV1Api(api_client) + v1.delete_namespaced_service(metadata["name"], metadata["namespace"], body=delete_options) + # Add more elif statements for other kinds of resources + +def get_custom_resource(): + print ("--- Retriving Kubernetes custom resource ---") + # Initialize Kubernetes configuration + #config.load_kube_config() + config.load_kube_config(config_file='/home/ubuntu/.kube/config') + #config.load_kube_config(config_file='/home/ubuntu/.kube/edge-kubeconfig') + #config.load_kube_config(config_file='/home/ubuntu/.kube/edge01-kubeconfig') + #config.load_kube_config(config_file='/home/ubuntu/.kube/edge02-kubeconfig') + #config.load_kube_config(config_file='/home/ubuntu/.kube/regional-kubeconfig') + #config.load_kube_config(config_file='/home/ubuntu/.kube/core-kubeconfig') + + #print(config.load_kube_config()) + #kubernetes.config.load_config() + + # Create a dynamic client + #dyn_client = client.DynamicClient(client.ApiClient()) + dyn_client = DynamicClient(client.ApiClient()) + + # Specify custom resource details + group = "config.porch.kpt.dev" + version = "v1alpha1" + plural = "PackageVariant" + + # Retrieve custom resources + custom_resources = dyn_client.resources.get(api_version=f"{group}/{version}", kind=plural) + print(custom_resources) + #resource_details = custom_resources.get(name="oai-cuup") + #print(resource_details) + + resource_list = custom_resources.get() + for resource in resource_list.items: + if resource.metadata.name == "oai-cuup": + print(json.dumps(resource.to_dict(), indent=2)) + + +def get_remote_file(): + # URL of the file to be downloaded + url = 'https://gist.githubusercontent.com/sdenel/1bd2c8b5975393ababbcff9b57784e82/raw/f1b885349ba17cb2a81ca3899acc86c6ad150eb1/nginx-hello-world-deployment.yaml' + #url = 'https://raw.githubusercontent.com/nephio-project/catalog/main/workloads/oai/package-variants/oai-du.yaml' + #url = 'https://raw.githubusercontent.com/nephio-project/catalog/main/workloads/oai/package-variants/oai-cucp.yaml' + #url = 'https://raw.githubusercontent.com/nephio-project/catalog/main/workloads/oai/package-variants/oai-cuup.yaml' + # Send a HTTP request to the URL of the file + response = requests.get(url) + + # Check if the request was successful + if response.status_code == 200: + # Open the file in write mode + with open('nginx-deployment.yaml', 'wb') as file: + # Write the contents of the response to the file + file.write(response.content) + else: + print('Failed to download the file.') + +if __name__ == "__main__": + main() + + + + + + + diff --git a/nfo/k8s/examples/crd/crd.yaml b/nfo/k8s/examples/crd/crd.yaml new file mode 100644 index 0000000..6c1ff1c --- /dev/null +++ b/nfo/k8s/examples/crd/crd.yaml @@ -0,0 +1,27 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + # name must be in the form: . + name: myapps.example.com + namespace: default +spec: + # group name to use for REST API: /apis// + group: example.com + scope: Namespaced + names: + # kind is normally the CamelCased singular type. + kind: MyApp + # singular name to be used as an alias on the CLI + singular: myapp + # plural name in the URL: /apis/// + plural: myapps + versions: + - name: v1 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + properties: + spec: + x-kubernetes-preserve-unknown-fields: true \ No newline at end of file diff --git a/nfo/k8s/examples/crd/test-app.yaml b/nfo/k8s/examples/crd/test-app.yaml new file mode 100644 index 0000000..4710225 --- /dev/null +++ b/nfo/k8s/examples/crd/test-app.yaml @@ -0,0 +1,10 @@ +apiVersion: example.com/v1 +kind: MyApp +metadata: + name: test-app + namespace: default +spec: + replicas: 3 + environment: dev + version: release-1.0.0 + language: golang \ No newline at end of file diff --git a/nfo/k8s/examples/nginx-deployment.yaml b/nfo/k8s/examples/nginx-deployment.yaml new file mode 100644 index 0000000..fb7ce9f --- /dev/null +++ b/nfo/k8s/examples/nginx-deployment.yaml @@ -0,0 +1,70 @@ +# To deploy: kubectl create -f nginx-hello-world-deployment.yaml +# Access it with the API as a proxy: +# $ kubectl proxy +# Then in you browser: http://localhost:8001/api/v1/namespaces/default/services/nginx:/proxy/#!/ + +apiVersion: v1 +kind: Service +metadata: + name: nginx + namespace: default +spec: + type: NodePort + ports: + - port: 80 + targetPort: 80 + nodePort: 30001 + selector: + app: nginx + +apiVersion: v1 +kind: ConfigMap +metadata: + name: nginx-config + namespace: default +data: + nginx.conf: ' +events { +} +http { + server { + listen 80; + location / { + return 200 "Hello world!"; + } + } +} +' + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx + namespace: default +spec: + selector: + matchLabels: + app: nginx + strategy: + type: Recreate + template: + metadata: + labels: + app: nginx + spec: + containers: + - image: nginx:latest + name: nginx + ports: + - containerPort: 80 + name: web + volumeMounts: + - name: config-vol + mountPath: /etc/nginx/ + volumes: + - name: config-vol + configMap: + name: nginx-config + items: + - key: nginx.conf + path: nginx.conf \ No newline at end of file diff --git a/nfo/k8s/examples/oai/oai-cucp.yaml b/nfo/k8s/examples/oai/oai-cucp.yaml new file mode 100644 index 0000000..bd71f3f --- /dev/null +++ b/nfo/k8s/examples/oai/oai-cucp.yaml @@ -0,0 +1,16 @@ +apiVersion: config.porch.kpt.dev/v1alpha1 +kind: PackageVariant +metadata: + name: regional-oai-cucp +spec: + upstream: + repo: catalog-workloads-oai + package: pkg-example-cucp-bp + revision: v2.0.0 + downstream: + repo: regional + package: oai-ran-cucp + annotations: + approval.nephio.org/policy: initial + injectors: + - name: regional diff --git a/nfo/k8s/examples/oai/oai-cuup.yaml b/nfo/k8s/examples/oai/oai-cuup.yaml new file mode 100644 index 0000000..af5ce99 --- /dev/null +++ b/nfo/k8s/examples/oai/oai-cuup.yaml @@ -0,0 +1,17 @@ +apiVersion: config.porch.kpt.dev/v1alpha1 +kind: PackageVariant +metadata: + name: edge-oai-cuup-test +spec: + upstream: + #repo: catalog-workloads-oai + repo: catalog-workloads-oai-ran + package: pkg-example-cuup-bp + revision: v2.0.0 + downstream: + repo: edge + package: oai-ran-cuup + annotations: + approval.nephio.org/policy: initial + injectors: + - name: edge \ No newline at end of file diff --git a/nfo/k8s/examples/oai/oai-du.yaml b/nfo/k8s/examples/oai/oai-du.yaml new file mode 100644 index 0000000..f078a1e --- /dev/null +++ b/nfo/k8s/examples/oai/oai-du.yaml @@ -0,0 +1,16 @@ +apiVersion: config.porch.kpt.dev/v1alpha1 +kind: PackageVariant +metadata: + name: edge-oai-du +spec: + upstream: + repo: catalog-workloads-oai + package: pkg-example-du-bp + revision: v2.0.0 + downstream: + repo: edge + package: oai-ran-du + annotations: + approval.nephio.org/policy: initial + injectors: + - name: edge diff --git a/nfo/k8s/examples/postman/osc_nfo.postman_collection_v3.0.json b/nfo/k8s/examples/postman/osc_nfo.postman_collection_v3.0.json new file mode 100644 index 0000000..cff26af --- /dev/null +++ b/nfo/k8s/examples/postman/osc_nfo.postman_collection_v3.0.json @@ -0,0 +1,782 @@ +{ + "info": { + "_postman_id": "a7ff689c-6dee-4c52-b1d4-66e6b182b7c0", + "name": "osc_nfo", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "2216531" + }, + "item": [ + { + "name": "helm", + "item": [ + { + "name": "Create Chart", + "request": { + "method": "POST", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"charts\": [\r\n {\r\n \"name\": \"cert-manager\",\r\n \"version\": \"v1.8.x\",\r\n \"repo\": \"https://charts.jetstack.io\"\r\n \r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "" + ] + } + }, + "response": [] + }, + { + "name": "OAI DU", + "request": { + "method": "POST", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": " {\r\n \"charts\": [\r\n {\r\n \"name\": \"oai-du\",\r\n \"version\": \"2.1.0\",\r\n \"repo\": \"https://gitlab.eurecom.fr/api/v4/projects/6252/packages/helm/main\"\r\n\r\n }\r\n ]\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/helm/du/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "helm", + "du", + "" + ] + } + }, + "response": [] + }, + { + "name": "OAI CU-CP", + "request": { + "method": "POST", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "\r\n {\r\n \"charts\": [\r\n {\r\n \"name\": \"oai-cu-cp\",\r\n \"version\": \"2.1.0\",\r\n \"repo\": \"https://gitlab.eurecom.fr/api/v4/projects/6252/packages/helm/main\"\r\n\r\n }\r\n ]\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/helm/cucp/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "helm", + "cucp", + "" + ] + } + }, + "response": [] + }, + { + "name": "OAI CU-UP", + "request": { + "method": "POST", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "\r\n {\r\n \"charts\": [\r\n {\r\n \"name\": \"oai-cu-up\",\r\n \"version\": \"2.1.0\",\r\n \"repo\": \"https://gitlab.eurecom.fr/api/v4/projects/6252/packages/helm/main\"\r\n\r\n }\r\n ]\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/helm/cuup/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "helm", + "cuup", + "" + ] + } + }, + "response": [] + }, + { + "name": "Delete Chart", + "request": { + "method": "DELETE", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"name\": \"cert-manager\",\r\n \"namespace\": \"default\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "" + ] + } + }, + "response": [] + }, + { + "name": "Delete OAI DU", + "request": { + "method": "DELETE", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"name\": \"oai-du\",\r\n \"namespace\": \"default\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/helm/du/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "helm", + "du", + "" + ] + } + }, + "response": [] + }, + { + "name": "Delete OAI CU-CP", + "request": { + "method": "DELETE", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"name\": \"oai-cu-cp\",\r\n \"namespace\": \"default\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/helm/cucp/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "helm", + "cucp", + "" + ] + } + }, + "response": [] + }, + { + "name": "Delete OAI CU-UP", + "request": { + "method": "DELETE", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"name\": \"oai-cu-up\",\r\n \"namespace\": \"default\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/helm/cuup/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "helm", + "cuup", + "" + ] + } + }, + "response": [] + }, + { + "name": "Get Charts", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/helm/du/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "helm", + "du", + "" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "operator", + "item": [ + { + "name": "OAI DU packagevariant", + "request": { + "method": "POST", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"pv\": \"oai-du\",\r\n \"pv-location\": \"https://raw.githubusercontent.com/nephio-project/catalog/main/workloads/oai/package-variants/oai-du.yaml\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/operator/du/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "operator", + "du", + "" + ] + } + }, + "response": [] + }, + { + "name": "OAI DU packagevariant", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"group\": \"config.porch.kpt.dev\",\r\n \"version\": \"v1alpha1\",\r\n \"plural\": \"PackageVariant\",\r\n \"name\": \"edge-oai-du\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/operator/du/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "operator", + "du", + "" + ] + } + }, + "response": [] + }, + { + "name": "Delete OAI DU packagevariant", + "request": { + "method": "DELETE", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"group\": \"config.porch.kpt.dev\",\r\n \"version\": \"v1alpha1\",\r\n \"namespace\": \"default\",\r\n \"plural\": \"packagevariants\",\r\n \"name\": \"edge-oai-du\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/operator/du/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "operator", + "du", + "" + ] + } + }, + "response": [] + }, + { + "name": "OAI CU-CP packagevariant", + "request": { + "method": "POST", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"pv\": \"oai-cucp\",\r\n \"pv-location\": \"https://raw.githubusercontent.com/nephio-project/catalog/main/workloads/oai/package-variants/oai-cucp.yaml\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/operator/cucp/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "operator", + "cucp", + "" + ] + } + }, + "response": [] + }, + { + "name": "OAI CU-CP packagevariant", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"group\": \"config.porch.kpt.dev\",\r\n \"version\": \"v1alpha1\",\r\n \"plural\": \"PackageVariant\",\r\n \"name\": \"regional-oai-cucp-test\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/operator/cucp", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "operator", + "cucp" + ] + } + }, + "response": [] + }, + { + "name": "Delete OAI CU-CP packagevariant", + "request": { + "method": "DELETE", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"group\": \"config.porch.kpt.dev\",\r\n \"version\": \"v1alpha1\",\r\n \"namespace\": \"default\",\r\n \"plural\": \"packagevariants\",\r\n \"name\": \"regional-oai-cucp-test\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/operator/cucp", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "operator", + "cucp" + ] + } + }, + "response": [] + }, + { + "name": "OAI CU-UP packagevariant", + "request": { + "method": "POST", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"pv\": \"oai-cuup\",\r\n \"pv-location\": \"https://raw.githubusercontent.com/nephio-project/catalog/main/workloads/oai/package-variants/oai-cuup.yaml\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/operator/cuup/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "operator", + "cuup", + "" + ] + } + }, + "response": [] + }, + { + "name": "OAI CU-UP packagevariant", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"group\": \"config.porch.kpt.dev\",\r\n \"version\": \"v1alpha1\",\r\n \"plural\": \"PackageVariant\",\r\n \"name\": \"edge-oai-cuup-test\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/operator/cuup/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "operator", + "cuup", + "" + ] + } + }, + "response": [] + }, + { + "name": "Delete OAI CU-UP packagevariant", + "request": { + "method": "DELETE", + "header": [ + { + "key": "X-CSRFToken", + "value": "1234", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"group\": \"config.porch.kpt.dev\",\r\n \"version\": \"v1alpha1\",\r\n \"namespace\": \"default\",\r\n \"plural\": \"packagevariants\",\r\n \"name\": \"edge-oai-cuup-test\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://127.0.0.1:8000/nfo/api/v1/operator/cuup/", + "protocol": "http", + "host": [ + "127", + "0", + "0", + "1" + ], + "port": "8000", + "path": [ + "nfo", + "api", + "v1", + "operator", + "cuup", + "" + ] + } + }, + "response": [] + } + ] + } + ] +} \ No newline at end of file diff --git a/nfo/k8s/helm_processor/__init__.py b/nfo/k8s/helm_processor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/nfo/k8s/helm_processor/admin.py b/nfo/k8s/helm_processor/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/nfo/k8s/helm_processor/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/nfo/k8s/helm_processor/apps.py b/nfo/k8s/helm_processor/apps.py new file mode 100644 index 0000000..7e55149 --- /dev/null +++ b/nfo/k8s/helm_processor/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class HelmProcessorConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'helm_processor' diff --git a/nfo/k8s/helm_processor/migrations/__init__.py b/nfo/k8s/helm_processor/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/nfo/k8s/helm_processor/models.py b/nfo/k8s/helm_processor/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/nfo/k8s/helm_processor/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/nfo/k8s/helm_processor/tests.py b/nfo/k8s/helm_processor/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/nfo/k8s/helm_processor/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/nfo/k8s/helm_processor/urls.py b/nfo/k8s/helm_processor/urls.py new file mode 100644 index 0000000..68fb2ca --- /dev/null +++ b/nfo/k8s/helm_processor/urls.py @@ -0,0 +1,27 @@ +""" +URL configuration for nfo_microservice project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.0/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +# include necessary libraries +from django.urls import path, include +from .views import du_processor, cucp_processor, cuup_processor + +urlpatterns = [ + path('admin/', admin.site.urls), + path('nfo/api/v1/helm/du/', du_processor), + path('nfo/api/v1/helm/cucp/', cucp_processor), + path('nfo/api/v1/helm/cuup/', cuup_processor), +] diff --git a/nfo/k8s/helm_processor/views.py b/nfo/k8s/helm_processor/views.py new file mode 100644 index 0000000..3471830 --- /dev/null +++ b/nfo/k8s/helm_processor/views.py @@ -0,0 +1,157 @@ +from django.shortcuts import render +from django.http import HttpResponse, JsonResponse +import asyncio +from pyhelm3 import Client +from django.views.decorators.csrf import csrf_exempt +from rest_framework.decorators import api_view +import json +from rest_framework import status +from rest_framework.response import Response +from configparser import ConfigParser + +@csrf_exempt +@api_view(['GET', 'POST', 'DELETE']) +def du_processor(request): + if request.method == "GET": + result = executeGet() + if request.method == "DELETE": + result = "Uninstalled !!" + executeDelete(request) + elif request.method == "POST": + executPost(request) + result = "Installed !!" + return JsonResponse(result, safe=False) + +@csrf_exempt +@api_view(['GET', 'POST', 'DELETE']) +def cucp_processor(request): + if request.method == "GET": + result = executeGet() + if request.method == "DELETE": + result = "Uninstalled !!" + executeDelete(request) + elif request.method == "POST": + executPost(request) + result = "Installed !!" + return JsonResponse(result, safe=False) + +@csrf_exempt +@api_view(['GET', 'POST', 'DELETE']) +def cuup_processor(request): + if request.method == "GET": + result = executeGet() + if request.method == "DELETE": + result = "Uninstalled !!" + executeDelete(request) + elif request.method == "POST": + executPost(request) + result = "Installed !!" + return JsonResponse(result, safe=False) + +def executeDelete(request): + print ("Delete request !!") + data = request.data + payload = json.loads(json.dumps(data)) + name = payload['name'] + namespace = payload['namespace'] + print ("chart name: "+ name + " chart namespace: "+ namespace ) + return asyncio.run(uninstall_helm(name, namespace)) + +async def uninstall_helm(name, namespace): + client = getHelmClient() + + revision = await client.get_current_revision(name, namespace = namespace) + await revision.release.uninstall(wait = True) + # Or directly by name + await client.uninstall_release(name, namespace = "default", wait = True) + return Response("Uninstalled", status=status.HTTP_201_CREATED) + +def executeGet(): + print ("Get request !!") + return asyncio.run(list_releases()) + +async def list_releases(): + client = getHelmClient() + + # List the deployed releases + releases = await client.list_releases(all = True, all_namespaces = True) + charts = [] + chart = {} + for release in releases: + revision = await release.current_revision() + print(release.name, release.namespace, revision.revision, str(revision.status)) + chart['name'] = release.name + chart['revision'] = revision.revision + chart['namespace'] = release.namespace + chart['status'] = str(revision.status) + charts.append(chart) + + result = json.dumps(charts) + return result + +def executPost(request): + print ("POST request !!") + data = request.data + payload = json.loads(json.dumps(data)) + charts = payload['charts'] + for chart in charts: + name = chart['name'] + version = chart['version'] + repo = chart['repo'] + print ("chart name: "+ name + " chart version: "+ version + " chart repo: " + repo) + asyncio.run(porcessCharts(name, version, repo)) + +async def porcessCharts(name, version, repo): + print ("Post request !!") + + client = getHelmClient() + + # Fetch a chart + chart = await client.get_chart( + name, + repo = repo, + version = version + ) + print(chart.metadata.name, chart.metadata.version) + #print(await chart.readme()) + + # Install or upgrade a release + revision = await client.install_or_upgrade_release( + name, + chart, + { "installCRDs": True }, + atomic = True, + wait = True + ) + print( + revision.release.name, + revision.release.namespace, + revision.revision, + str(revision.status) + ) + + content = { revision.release.name, revision.release.namespace, revision.revision, str(revision.status)} + return Response(content, status=status.HTTP_201_CREATED) + +def getHelmClient(): + + config = ConfigParser() + with open("config.ini", "r") as file_object: + config.read_file(file_object) + kube_config = config.get("localpath", "kubeconfig_file_path") + helm_executable = config.get("localpath", "helm_executable_path") + + # This will use the Kubernetes configuration from the environment + client = Client() + # Specify the kubeconfig file to use + client = Client(kubeconfig = kube_config) + # Specify a custom Helm executable (by default, we expect 'helm' to be on the PATH) + client = Client(executable = helm_executable) + + return client + + + + + +# Create your views here. diff --git a/nfo/k8s/nfo_microservice/__init__.py b/nfo/k8s/nfo_microservice/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/nfo/k8s/nfo_microservice/__init__.py @@ -0,0 +1 @@ + diff --git a/nfo/k8s/nfo_microservice/asgi.py b/nfo/k8s/nfo_microservice/asgi.py new file mode 100644 index 0000000..e527885 --- /dev/null +++ b/nfo/k8s/nfo_microservice/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for nfo_microservice project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'nfo_microservice.settings') + +application = get_asgi_application() diff --git a/nfo/k8s/nfo_microservice/settings.py b/nfo/k8s/nfo_microservice/settings.py new file mode 100644 index 0000000..de1e6a2 --- /dev/null +++ b/nfo/k8s/nfo_microservice/settings.py @@ -0,0 +1,126 @@ +""" +Django settings for nfo_microservice project. + +Generated by 'django-admin startproject' using Django 5.0.3. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.0/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-@2#ob=f_mn7-8#)(v+*yc9yx3(l(h&av5rjna5$)gv4qevq61v' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'rest_framework', + 'helm_processor', + 'packagevariant_processor', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'nfo_microservice.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'nfo_microservice.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/5.0/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.0/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.0/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/nfo/k8s/nfo_microservice/urls.py b/nfo/k8s/nfo_microservice/urls.py new file mode 100644 index 0000000..7da94f0 --- /dev/null +++ b/nfo/k8s/nfo_microservice/urls.py @@ -0,0 +1,27 @@ +""" +URL configuration for nfo_microservice project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.0/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +# include necessary libraries +from django.urls import path, include +from .views import home_page + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include("helm_processor.urls")), + path('', include("packagevariant_processor.urls")), + +] diff --git a/nfo/k8s/nfo_microservice/views.py b/nfo/k8s/nfo_microservice/views.py new file mode 100644 index 0000000..b6d77af --- /dev/null +++ b/nfo/k8s/nfo_microservice/views.py @@ -0,0 +1,131 @@ +from django.http import HttpResponse, JsonResponse +import asyncio +from pyhelm3 import Client +from django.views.decorators.csrf import csrf_exempt +from rest_framework.decorators import api_view +import json +from rest_framework import status +from rest_framework.response import Response +from configparser import ConfigParser + +@csrf_exempt +@api_view(['GET', 'POST', 'DELETE']) +def home_page(request): + books = ['selfhelp','fantacy','novels'] + #return HttpResponse("

This is home page !!

") + + if request.method == "GET": + result = executeGet() + if request.method == "DELETE": + result = "Uninstalled !!" + executeDelete(request) + elif request.method == "POST": + executPost(request) + result = "Installed !!" + + return JsonResponse(result, safe=False) + +def executeDelete(request): + print ("Delete request !!") + data = request.data + payload = json.loads(json.dumps(data)) + name = payload['name'] + namespace = payload['namespace'] + print ("chart name: "+ name + " chart namespace: "+ namespace ) + return asyncio.run(uninstall_helm(name, namespace)) + +async def uninstall_helm(name, namespace): + client = getHelmClient() + + revision = await client.get_current_revision(name, namespace = namespace) + await revision.release.uninstall(wait = True) + # Or directly by name + await client.uninstall_release(name, namespace = "default", wait = True) + return Response("Uninstalled", status=status.HTTP_201_CREATED) + +def executeGet(): + print ("Get request !!") + return asyncio.run(list_releases()) + +async def list_releases(): + client = getHelmClient() + + # List the deployed releases + releases = await client.list_releases(all = True, all_namespaces = True) + charts = [] + chart = {} + for release in releases: + revision = await release.current_revision() + print(release.name, release.namespace, revision.revision, str(revision.status)) + chart['name'] = release.name + chart['revision'] = revision.revision + chart['namespace'] = release.namespace + chart['status'] = str(revision.status) + charts.append(chart) + + result = json.dumps(charts) + return result + +def executPost(request): + print ("POST request !!") + data = request.data + payload = json.loads(json.dumps(data)) + charts = payload['charts'] + for chart in charts: + name = chart['name'] + version = chart['version'] + repo = chart['repo'] + print ("chart name: "+ name + " chart version: "+ version + " chart repo: " + repo) + asyncio.run(porcessCharts(name, version, repo)) + +async def porcessCharts(name, version, repo): + print ("Post request !!") + + client = getHelmClient() + + # Fetch a chart + chart = await client.get_chart( + name, + repo = repo, + version = version + ) + print(chart.metadata.name, chart.metadata.version) + #print(await chart.readme()) + + # Install or upgrade a release + revision = await client.install_or_upgrade_release( + name, + chart, + { "installCRDs": True }, + atomic = True, + wait = True + ) + print( + revision.release.name, + revision.release.namespace, + revision.revision, + str(revision.status) + ) + + content = { revision.release.name, revision.release.namespace, revision.revision, str(revision.status)} + return Response(content, status=status.HTTP_201_CREATED) + +def getHelmClient(): + + config = ConfigParser() + with open("config.ini", "r") as file_object: + config.read_file(file_object) + kube_config = config.get("localpath", "kubeconfig_file_path") + helm_executable = config.get("localpath", "helm_executable_path") + + # This will use the Kubernetes configuration from the environment + client = Client() + # Specify the kubeconfig file to use + client = Client(kubeconfig = kube_config) + # Specify a custom Helm executable (by default, we expect 'helm' to be on the PATH) + client = Client(executable = helm_executable) + + return client + + + diff --git a/nfo/k8s/nfo_microservice/wsgi.py b/nfo/k8s/nfo_microservice/wsgi.py new file mode 100644 index 0000000..5e4b2d4 --- /dev/null +++ b/nfo/k8s/nfo_microservice/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for nfo_microservice project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'nfo_microservice.settings') + +application = get_wsgi_application() diff --git a/nfo/k8s/packagevariant_processor/__init__.py b/nfo/k8s/packagevariant_processor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/nfo/k8s/packagevariant_processor/admin.py b/nfo/k8s/packagevariant_processor/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/nfo/k8s/packagevariant_processor/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/nfo/k8s/packagevariant_processor/apps.py b/nfo/k8s/packagevariant_processor/apps.py new file mode 100644 index 0000000..74a6d72 --- /dev/null +++ b/nfo/k8s/packagevariant_processor/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class PackagevariantProcessorConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'packagevariant_processor' diff --git a/nfo/k8s/packagevariant_processor/models.py b/nfo/k8s/packagevariant_processor/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/nfo/k8s/packagevariant_processor/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/nfo/k8s/packagevariant_processor/tests.py b/nfo/k8s/packagevariant_processor/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/nfo/k8s/packagevariant_processor/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/nfo/k8s/packagevariant_processor/urls.py b/nfo/k8s/packagevariant_processor/urls.py new file mode 100644 index 0000000..ebaa5ad --- /dev/null +++ b/nfo/k8s/packagevariant_processor/urls.py @@ -0,0 +1,27 @@ +""" +URL configuration for nfo_microservice project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.0/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +# include necessary libraries +from django.urls import path, include +from .views import du_processor, cucp_processor, cuup_processor + +urlpatterns = [ + path('admin/', admin.site.urls), + path('nfo/api/v1/operator/du/', du_processor), + path('nfo/api/v1/operator/cucp/', cucp_processor), + path('nfo/api/v1/operator/cuup/', cuup_processor), +] diff --git a/nfo/k8s/packagevariant_processor/views.py b/nfo/k8s/packagevariant_processor/views.py new file mode 100644 index 0000000..6123d03 --- /dev/null +++ b/nfo/k8s/packagevariant_processor/views.py @@ -0,0 +1,146 @@ +from django.shortcuts import render +from django.views.decorators.csrf import csrf_exempt +from rest_framework.decorators import api_view +from django.http import HttpResponse, JsonResponse +from kubernetes import client, config, utils +import requests +import yaml +from kubernetes.dynamic import DynamicClient +import json +from rest_framework.renderers import JSONRenderer + +# Create your views here. + +@csrf_exempt +@api_view(['GET', 'POST', 'DELETE']) +def du_processor(request): + if request.method == "GET": + result = executeGet(request) + if request.method == "DELETE": + executeDelete(request) + result = "Deleted !!" + elif request.method == "POST": + result = executePost(request) + + return JsonResponse(result, safe=False) + +@csrf_exempt +@api_view(['GET', 'POST', 'DELETE']) +def cucp_processor(request): + if request.method == "GET": + result = executeGet(request) + if request.method == "DELETE": + executeDelete(request) + result = "Deleted !!" + elif request.method == "POST": + result = executePost(request) + + return JsonResponse(result, safe=False) + +@csrf_exempt +@api_view(['GET', 'POST', 'DELETE']) +def cuup_processor(request): + if request.method == "GET": + result = executeGet(request) + if request.method == "DELETE": + executeDelete(request) + result = "Deleted !!" + elif request.method == "POST": + result = executePost(request) + + return JsonResponse(result, safe=False) + +def executePost(request): + data = request.data + payload = json.loads(json.dumps(data)) + pv = payload['pv'] + pv_location = payload['pv-location'] + + get_remote_file(pv, pv_location) + # Load kube config + #config.load_kube_config() + config.load_kube_config(config_file='/home/ubuntu/.kube/config') + + # Create a dynamic client + dyn_client = DynamicClient(client.ApiClient()) + + with open("examples/oai/"+ pv +".yaml", "r") as stream: + custom_resource = yaml.safe_load(stream) + print (custom_resource) + + # Create the custom resource using the dynamic client + my_resource = dyn_client.resources.get(api_version='config.porch.kpt.dev/v1alpha1', kind='PackageVariant') + created_resource = my_resource.create(body=custom_resource, namespace='default') + print(f"Created resource mycrd") + cuup_res = json.dumps(created_resource.to_dict(), indent=2) + print (cuup_res) + return cuup_res + +def executeDelete(request): + data = request.data + payload = json.loads(json.dumps(data)) + group = payload['group'] + version = payload['version'] + namespace = payload['namespace'] + plural = payload['plural'] + name = payload['name'] + + # Load kube config + #config.load_kube_config() + config.load_kube_config(config_file='/home/ubuntu/.kube/config') + + # Create a CustomObjectsAPI instance + custom_api = client.CustomObjectsApi() + + # Delete the custom resource + custom_api.delete_namespaced_custom_object( + group = group, + version = version, + namespace = namespace, + plural = plural, + name = name + ) + +def executeGet(request): + data = request.data + payload = json.loads(json.dumps(data)) + group = payload['group'] + version = payload['version'] + plural = payload['plural'] + name = payload['name'] + + print ("--- Retriving Kubernetes custom resource ---") + config.load_kube_config(config_file='/home/ubuntu/.kube/config') + + dyn_client = DynamicClient(client.ApiClient()) + + # Specify custom resource details + group = group + version = version + plural = plural + + # Retrieve custom resources + custom_resources = dyn_client.resources.get(api_version=f"{group}/{version}", kind=plural) + print(custom_resources) + #resource_details = custom_resources.get(name="oai-cuup") + #print(resource_details) + + resource_list = custom_resources.get() + for resource in resource_list.items: + if resource.metadata.name == name: + cucp_res = json.dumps(resource.to_dict(), indent=2) + print (cucp_res) + return cucp_res + +def get_remote_file(pv, pv_location): + # Send a HTTP request to the URL of the file + response = requests.get(pv_location) + + # Check if the request was successful + if response.status_code == 200: + # Open the file in write mode + with open('examples/oai/'+ pv +'.yaml', 'wb') as file: + # Write the contents of the response to the file + file.write(response.content) + else: + print('Failed to download the file.')