From eef9fef1141c6295b824b884ad86d645cd1c094f Mon Sep 17 00:00:00 2001 From: shreyagupta30 Date: Mon, 27 Sep 2021 14:35:36 +0530 Subject: Automated deployment of helm charts with python This patch adds demo helm charts and a python script that automatically deploys any helm chart of user's choice and print all the useful information about the chart. Signed-off-by: Shreya Gupta Change-Id: I06e3a8012602e09f601f70def386ef267c870e94 --- tools/k8s/app-deployment/helm/charts/mynet.yaml | 20 +++ tools/k8s/app-deployment/helm/charts/pod.yaml | 18 +++ .../helm/charts/proxchart/Chart.yaml | 5 + .../helm/charts/proxchart/templates/daemonset.yaml | 25 +++ .../charts/proxchart/templates/deployment.yaml | 30 ++++ .../helm/charts/proxchart/templates/service.yaml | 11 ++ .../helm/charts/proxchart/values.yaml | 20 +++ .../helm/charts/testpmdchart/Chart.yaml | 5 + .../charts/testpmdchart/templates/daemonset.yaml | 25 +++ .../charts/testpmdchart/templates/deployment.yaml | 26 ++++ .../charts/testpmdchart/templates/service.yaml | 11 ++ .../helm/charts/testpmdchart/values.yaml | 20 +++ .../helm/charts/trexchart/Chart.yaml | 5 + .../helm/charts/trexchart/templates/daemonset.yaml | 25 +++ .../charts/trexchart/templates/deployment.yaml | 26 ++++ .../helm/charts/trexchart/templates/service.yaml | 11 ++ .../helm/charts/trexchart/values.yaml | 20 +++ tools/k8s/app-deployment/helm/pyscript/Pipfile | 18 +++ tools/k8s/app-deployment/helm/pyscript/main.py | 172 +++++++++++++++++++++ 19 files changed, 493 insertions(+) create mode 100644 tools/k8s/app-deployment/helm/charts/mynet.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/pod.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/proxchart/Chart.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/proxchart/templates/daemonset.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/proxchart/templates/deployment.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/proxchart/templates/service.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/proxchart/values.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/testpmdchart/Chart.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/testpmdchart/templates/daemonset.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/testpmdchart/templates/deployment.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/testpmdchart/templates/service.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/testpmdchart/values.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/trexchart/Chart.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/trexchart/templates/daemonset.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/trexchart/templates/deployment.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/trexchart/templates/service.yaml create mode 100644 tools/k8s/app-deployment/helm/charts/trexchart/values.yaml create mode 100644 tools/k8s/app-deployment/helm/pyscript/Pipfile create mode 100644 tools/k8s/app-deployment/helm/pyscript/main.py (limited to 'tools/k8s') diff --git a/tools/k8s/app-deployment/helm/charts/mynet.yaml b/tools/k8s/app-deployment/helm/charts/mynet.yaml new file mode 100644 index 00000000..ca3af9a7 --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/mynet.yaml @@ -0,0 +1,20 @@ +apiVersion: "k8s.cni.cncf.io/v1" +kind: NetworkAttachmentDefinition +metadata: + name: mynet +spec: + config: '{ + "cniVersion":"0.3.0" + "name":"mynet" + "plugins":[ + { + "bridge":"kube-bridge", + "ipam":{ + "subnet":10.244.0.0/24", + "type":"host-local" + }, + "isDefaultGateway":true, + "type":"bridge" + } + ] + }' diff --git a/tools/k8s/app-deployment/helm/charts/pod.yaml b/tools/k8s/app-deployment/helm/charts/pod.yaml new file mode 100644 index 00000000..942c8f97 --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/pod.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx + annotations: + k8s.v1.cni.cncf.io/networks: mynet + +spec: + containers: + - name: prox + image: opnfv/rapid:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3000 + - name: nginx + image: nginx:alpine + ports: + - containerPort: 80 diff --git a/tools/k8s/app-deployment/helm/charts/proxchart/Chart.yaml b/tools/k8s/app-deployment/helm/charts/proxchart/Chart.yaml new file mode 100644 index 00000000..6acc06f4 --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/proxchart/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +name: proxchart +version: 0.1.0 +appVersion: "1.0" +description: To deploy prox diff --git a/tools/k8s/app-deployment/helm/charts/proxchart/templates/daemonset.yaml b/tools/k8s/app-deployment/helm/charts/proxchart/templates/daemonset.yaml new file mode 100644 index 00000000..e1d3a563 --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/proxchart/templates/daemonset.yaml @@ -0,0 +1,25 @@ +{{- if eq .Values.kind "DaemonSet"}} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: prox + annotations: + k8s.v1.cni.cncf.io/networks: "{{- join "\",\"" .Values.extraInterfaces }}" +spec: + selector: + matchLabels: + app: prox + template: + metadata: + labels: + app: prox + spec: + containers: + - name: prox + image: opnfv/rapid:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3000 + nodeSelector: + {{- .Values.nodeSelector.matchLables | toYaml | nindent 12 }} +{{- end }} diff --git a/tools/k8s/app-deployment/helm/charts/proxchart/templates/deployment.yaml b/tools/k8s/app-deployment/helm/charts/proxchart/templates/deployment.yaml new file mode 100644 index 00000000..235b02cd --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/proxchart/templates/deployment.yaml @@ -0,0 +1,30 @@ +{{- if eq .Values.kind "Deployment"}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: prox + annotations: + k8s.v1.cni.cncf.io/networks: "{{- join "\",\"" .Values.extraInterfaces | toYaml | nindent 8}}" +spec: + selector: + matchLabels: + app: prox + replicas: {{ .Values.replicas }} + template: + metadata: + labels: + app: prox + spec: + containers: + - name: prox + image: opnfv/rapid:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3000 + - name: nginx + image: nginx:alpine + ports: + - containerPort: 80 + nodeSelector: + {{- .Values.nodeSelector.matchLables | toYaml | nindent 12 }} +{{- end }} diff --git a/tools/k8s/app-deployment/helm/charts/proxchart/templates/service.yaml b/tools/k8s/app-deployment/helm/charts/proxchart/templates/service.yaml new file mode 100644 index 00000000..15215f35 --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/proxchart/templates/service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: proxchart +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http diff --git a/tools/k8s/app-deployment/helm/charts/proxchart/values.yaml b/tools/k8s/app-deployment/helm/charts/proxchart/values.yaml new file mode 100644 index 00000000..405e4c25 --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/proxchart/values.yaml @@ -0,0 +1,20 @@ +# daemonset, deployment +kind: Deployment + +# Nodes to deploy on +nodeSelector: {} + # matchLables: + # key1: value1 + # key2: value2 + +# multus +metacniType: multus +extraInterfaces: + net-attach-def1 + net-attach-def2 + +replicas: 1 + +service: + type: NodePort + port: 8081 diff --git a/tools/k8s/app-deployment/helm/charts/testpmdchart/Chart.yaml b/tools/k8s/app-deployment/helm/charts/testpmdchart/Chart.yaml new file mode 100644 index 00000000..85e8f7d0 --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/testpmdchart/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +name: testpmdchart +version: 0.1.0 +appVersion: "1.0" +description: To deploy test pmd diff --git a/tools/k8s/app-deployment/helm/charts/testpmdchart/templates/daemonset.yaml b/tools/k8s/app-deployment/helm/charts/testpmdchart/templates/daemonset.yaml new file mode 100644 index 00000000..10a812f6 --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/testpmdchart/templates/daemonset.yaml @@ -0,0 +1,25 @@ +{{- if eq .Values.kind "DaemonSet"}} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: testpmd + annotations: + k8s.v1.cni.cncf.io/networks: "{{- join "\",\"" .Values.extraInterfaces }}" +spec: + selector: + matchLabels: + app: testpmd + template: + metadata: + labels: + app: testpmd + spec: + containers: + - name: testpmd + image: ovsperf/dpdkfwd:lakelse + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3000 + nodeSelector: + {{- .Values.nodeSelector.matchLables | toYaml | nindent 12 }} +{{- end }} diff --git a/tools/k8s/app-deployment/helm/charts/testpmdchart/templates/deployment.yaml b/tools/k8s/app-deployment/helm/charts/testpmdchart/templates/deployment.yaml new file mode 100644 index 00000000..6df47ff1 --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/testpmdchart/templates/deployment.yaml @@ -0,0 +1,26 @@ +{{- if eq .Values.kind "Deployment"}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: testpmd + annotations: + k8s.v1.cni.cncf.io/networks: "{{- join "\",\"" .Values.extraInterfaces | toYaml | nindent 8}}" +spec: + selector: + matchLabels: + app: testpmd + replicas: {{ .Values.replicas }} + template: + metadata: + labels: + app: testpmd + spec: + containers: + - name: testpmd + image: vsperf/dpdkfwd:lakelse + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3000 + nodeSelector: + {{- .Values.nodeSelector.matchLables | toYaml | nindent 12 }} +{{- end }} diff --git a/tools/k8s/app-deployment/helm/charts/testpmdchart/templates/service.yaml b/tools/k8s/app-deployment/helm/charts/testpmdchart/templates/service.yaml new file mode 100644 index 00000000..50f75629 --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/testpmdchart/templates/service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: testpmdchart +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http diff --git a/tools/k8s/app-deployment/helm/charts/testpmdchart/values.yaml b/tools/k8s/app-deployment/helm/charts/testpmdchart/values.yaml new file mode 100644 index 00000000..af6be613 --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/testpmdchart/values.yaml @@ -0,0 +1,20 @@ +# daemonset, deployment +kind: Deployment + +# Nodes to deploy on +nodeSelector: + # matchLables: + # key1: value1 + # key2: value2 + +# multus +metacniType: multus +extraInterfaces: + net-attach-def1 + net-attach-def2 + +replicas: 1 + +service: + type: NodePort + port: 8081 diff --git a/tools/k8s/app-deployment/helm/charts/trexchart/Chart.yaml b/tools/k8s/app-deployment/helm/charts/trexchart/Chart.yaml new file mode 100644 index 00000000..1dfb7b0b --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/trexchart/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +name: trexchart +description: A Helm chart for trex Deployment +version: 0.1.0 +appVersion: "1.0" diff --git a/tools/k8s/app-deployment/helm/charts/trexchart/templates/daemonset.yaml b/tools/k8s/app-deployment/helm/charts/trexchart/templates/daemonset.yaml new file mode 100644 index 00000000..39d4662f --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/trexchart/templates/daemonset.yaml @@ -0,0 +1,25 @@ +{{- if eq .Values.kind "DaemonSet"}} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: trex + annotations: + k8s.v1.cni.cncf.io/networks: "{{- join "\",\"" .Values.extraInterfaces }}" +spec: + selector: + matchLabels: + app: trex + template: + metadata: + labels: + app: trex + spec: + containers: + - name: trex + image: vsperf/trex:lakelse + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3000 + nodeSelector: + {{- .Values.nodeSelector.matchLables | toYaml | nindent 12 }} +{{- end }} diff --git a/tools/k8s/app-deployment/helm/charts/trexchart/templates/deployment.yaml b/tools/k8s/app-deployment/helm/charts/trexchart/templates/deployment.yaml new file mode 100644 index 00000000..8b0f447e --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/trexchart/templates/deployment.yaml @@ -0,0 +1,26 @@ +{{- if eq .Values.kind "Deployment"}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: trex + annotations: + k8s.v1.cni.cncf.io/networks: "{{- join "\",\"" .Values.extraInterfaces | toYaml | nindent 8}}" +spec: + selector: + matchLabels: + app: trex + replicas: {{ .Values.replicas }} + template: + metadata: + labels: + app: trex + spec: + containers: + - name: trex + image: vsperf/trex:lakelse + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3000 + nodeSelector: + {{- .Values.nodeSelector.matchLables | toYaml | nindent 12 }} +{{- end }} diff --git a/tools/k8s/app-deployment/helm/charts/trexchart/templates/service.yaml b/tools/k8s/app-deployment/helm/charts/trexchart/templates/service.yaml new file mode 100644 index 00000000..8965194d --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/trexchart/templates/service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: trexchart +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http diff --git a/tools/k8s/app-deployment/helm/charts/trexchart/values.yaml b/tools/k8s/app-deployment/helm/charts/trexchart/values.yaml new file mode 100644 index 00000000..ed289cf9 --- /dev/null +++ b/tools/k8s/app-deployment/helm/charts/trexchart/values.yaml @@ -0,0 +1,20 @@ +# daemonset, deployment +kind: DaemonSet + +# Nodes to deploy on +nodeSelector: + # matchLables: + # key1: value1 + # key2: value2 + +# multus +metacniType: multus +extraInterfaces: + net-attach-def1 + net-attach-def2 + +replicas: 1 + +service: + type: NodePort + port: 8081 diff --git a/tools/k8s/app-deployment/helm/pyscript/Pipfile b/tools/k8s/app-deployment/helm/pyscript/Pipfile new file mode 100644 index 00000000..dd60181c --- /dev/null +++ b/tools/k8s/app-deployment/helm/pyscript/Pipfile @@ -0,0 +1,18 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +kubernetes = "*" +pyyaml = "*" +pick = "*" +simplejson = "*" +nested-lookup = "*" +rich = "*" +pylint = "*" + +[dev-packages] + +[requires] +python_version = "3.9" diff --git a/tools/k8s/app-deployment/helm/pyscript/main.py b/tools/k8s/app-deployment/helm/pyscript/main.py new file mode 100644 index 00000000..1419f345 --- /dev/null +++ b/tools/k8s/app-deployment/helm/pyscript/main.py @@ -0,0 +1,172 @@ +# Copyright 2015-2017 Intel Corporation. +# +# 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. + +''' +This script automatically develop helm charts and returns +useful informations +''' + +import os +import subprocess +from subprocess import PIPE, STDOUT +import time +import re +from ast import literal_eval +import yaml +from rich.console import Console +from rich.table import Table + +console = Console() + +def check_system_installations(): + ''' Check system installations necessary for successful run of this script ''' + try: + subprocess.run("helm version",shell=True,check=True) + subprocess.run("kubectl version --client",shell=True, + check= True) + subprocess.run("minikube version",shell=True,check=True) + + except subprocess.CalledProcessError as error: + print (error.output) + + +def parse_helm_chart(helm_path): + ''' Extract name of the chart ''' + values_file = os.path.join(helm_path,"Chart.yaml") + with open(values_file, 'r', encoding='utf-8') as file: + doc = yaml.load(file) + name_of_chart = doc['name'] + + values_file = os.path.join(helm_path,"values.yaml") + with open(values_file, 'r',encoding='utf-8') as file: + doc = yaml.load(file) + n_pods = doc['replicas'] + return (name_of_chart, n_pods) + + +def service_details(name): + ''' Extract Service Details''' + print("\nDEPLOYEMENT DETAILS\n") + + with subprocess.Popen(f"kubectl get service -o json {name}",shell=True, + stdin=PIPE, stdout=PIPE, stderr=STDOUT) as process: + output = process.stdout.read() + string = output.decode().replace("'", '"') + _j = literal_eval(string) + + table = Table(show_header=True) + + table.add_column("NAME") + table.add_column("Type") + table.add_column("CLUSTER-IP") + table.add_column("EXTERNAL-IP") + table.add_column("PORT(S)") + + col=f'{_j["spec"]["ports"][0]["port"]}:{_j["spec"]["ports"][0]["nodePort"]}/{_j["spec"]["ports"][0]["protocol"]}' + + table.add_row( + f'{_j["metadata"]["name"]}', + f'{_j["spec"]["type"]}', + f'{_j["spec"]["clusterIP"]}', + f'{_j["status"]["loadBalancer"]}', + col, + ) + console.print(table) + + +def pod_details(replicas): + ''' Extract Pod Details''' + print("\nPOD DETAILS\n") + with subprocess.Popen("kubectl get pods -o json", shell=True, + stdin=PIPE, stdout=PIPE, stderr=STDOUT) as process: + output = process.stdout.read() + pod_string = output.decode().replace("'", '"') + # true = True + # null = None + # false = False + pod_json = literal_eval(pod_string) + + table = Table(show_header=True) + + table.add_column("POD NAME") + table.add_column("NAMESPACE") + table.add_column("HOST-IP") + table.add_column("PHASE") + table.add_column("POD-IP") + table.add_column("POD-IPs") + podname = pod_json["items"][0]["metadata"]["name"] + + for i in range(replicas): + table.add_row( + f'{pod_json["items"][i]["metadata"]["name"]}', + f'{pod_json["items"][i]["metadata"]["namespace"]}', + f'{pod_json["items"][i]["status"]["hostIP"]}', + f'{pod_json["items"][i]["status"]["phase"]}', + f'{pod_json["items"][i]["status"]["podIP"]}', + f'{pod_json["items"][i]["status"]["podIPs"]}', + ) + console.print(table) + + ip_interface(podname) + + +def ip_interface(podname): + ''' Extract Network IP''' + with subprocess.Popen(f"kubectl exec -i {podname} -c nginx -- ip -o a", shell=True, + stdin=PIPE, stdout=PIPE, stderr=STDOUT) as process: + output = process.stdout.read() + _string = output.decode().replace("'", '"') + ipregex = r"((?:[0-9]{1,3}[.]){3}[0-9]{1,3}/[0-9]{1,2})" + ipregex2 = r"((?:[0-9]{1,3}[.]){3}[0-9]{1,3})" + list1=re.findall(ipregex, _string) + list2=re.findall(ipregex2 ,_string) + ip_list = list1 + list2 + ip_string = ', '.join(ip_list) + + table = Table(show_header=True) + + table.add_column("POD NAME") + table.add_column("INTERFACE IPs") + + table.add_row( + podname, + ip_string, + ) + console.print(table) + + +def main(): + ''' Main Function ''' + check_system_installations() + + helm_location = input("Enter the location of helm chart: ") + name,replicas = parse_helm_chart(helm_location) + + subprocess.run(f"helm install {name} {helm_location}",shell=True, + check = True).stdout.read() + time.sleep(10) + + # status of helm charts + print("\nStatus of helm charts\n") + subprocess.Popen("helm list", shell =True,stdout=subprocess.PIPE,).communicate() + print("--" * 50) + + #pod details + pod_details(replicas) + + #deployment details + service_details(name) + +if __name__ == "__main__": + main() -- cgit 1.2.3-korg