From 973866811e7e80864409fcb8fa25509ce133956e Mon Sep 17 00:00:00 2001 From: Surax98 Date: Mon, 22 Jul 2024 09:50:18 +0000 Subject: [PATCH] refactoring python script and getting openAPI spec complaint to current version Signed-off-by: Surax98 --- docs/openapi/openapi.json | 2 +- example/create_openapi.py | 4 +- example/interlink/provider.py | 18 ++--- example/interlink/spec.py | 92 ++++++++++----------- example/provider_demo.py | 148 +++++++++++++++++----------------- 5 files changed, 130 insertions(+), 134 deletions(-) diff --git a/docs/openapi/openapi.json b/docs/openapi/openapi.json index d783f5b6..4df5ccb9 100644 --- a/docs/openapi/openapi.json +++ b/docs/openapi/openapi.json @@ -1 +1 @@ -{"openapi": "3.1.0", "info": {"title": "interLink sidecar", "description": "openapi spec for interLink apis <-> provider sidecar communication", "version": "v0.0.0"}, "paths": {"/create": {"post": {"summary": "Create Pod", "operationId": "create_pod_create_post", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Pod"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateStruct"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/delete": {"post": {"summary": "Delete Pod", "operationId": "delete_pod_delete_post", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/PodRequest"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "string", "title": "Response Delete Pod Delete Post"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/status": {"get": {"summary": "Status Pod", "operationId": "status_pod_status_get", "requestBody": {"content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/PodRequest"}, "type": "array", "title": "Pods"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/PodStatus"}, "type": "array", "title": "Response Status Pod Status Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/getLogs": {"get": {"summary": "Get Logs", "operationId": "get_logs_getLogs_get", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/LogRequest"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"text/plain": {"schema": {"type": "string"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}}, "components": {"schemas": {"ConfigMap": {"properties": {"metadata": {"$ref": "#/components/schemas/Metadata"}, "data": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Data"}, "binaryData": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Binarydata"}, "type": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Type"}, "immutable": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Immutable"}}, "type": "object", "required": ["metadata", "data"], "title": "ConfigMap"}, "ConfigMapKeySelector": {"properties": {"key": {"type": "string", "title": "Key"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "optional": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Optional"}}, "type": "object", "required": ["key"], "title": "ConfigMapKeySelector"}, "ConfigMapVolumeSource": {"properties": {"name": {"type": "string", "title": "Name"}, "items": {"anyOf": [{"items": {"$ref": "#/components/schemas/KeyToPath"}, "type": "array"}, {"type": "null"}], "title": "Items", "default": []}, "optional": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Optional"}, "defaultMode": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Defaultmode"}}, "type": "object", "required": ["name"], "title": "ConfigMapVolumeSource"}, "Container": {"properties": {"name": {"type": "string", "title": "Name"}, "image": {"type": "string", "title": "Image"}, "tag": {"type": "string", "title": "Tag", "default": "latest"}, "command": {"items": {"type": "string"}, "type": "array", "title": "Command"}, "args": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "title": "Args", "default": []}, "resources": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Resources", "default": {}}, "volumeMounts": {"anyOf": [{"items": {"$ref": "#/components/schemas/VolumeMount"}, "type": "array"}, {"type": "null"}], "title": "Volumemounts", "default": []}, "env": {"anyOf": [{"items": {"$ref": "#/components/schemas/EnvVar"}, "type": "array"}, {"type": "null"}], "title": "Env"}, "securityContext": {"anyOf": [{"$ref": "#/components/schemas/SecurityContext"}, {"type": "null"}]}}, "type": "object", "required": ["name", "image", "command"], "title": "Container"}, "ContainerStates": {"properties": {"terminated": {"anyOf": [{"$ref": "#/components/schemas/StateTerminated"}, {"type": "null"}]}, "running": {"anyOf": [{"$ref": "#/components/schemas/StateRunning"}, {"type": "null"}]}, "waiting": {"anyOf": [{"$ref": "#/components/schemas/StateWaiting"}, {"type": "null"}]}}, "type": "object", "title": "ContainerStates"}, "ContainerStatus": {"properties": {"name": {"type": "string", "title": "Name"}, "state": {"$ref": "#/components/schemas/ContainerStates"}}, "type": "object", "required": ["name", "state"], "title": "ContainerStatus"}, "CreateStruct": {"properties": {"PodUID": {"type": "string", "title": "Poduid"}, "PodJID": {"type": "string", "title": "Podjid"}}, "type": "object", "required": ["PodUID", "PodJID"], "title": "CreateStruct"}, "EnvVar": {"properties": {"name": {"type": "string", "title": "Name"}, "value": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Value"}, "valueFrom": {"anyOf": [{"$ref": "#/components/schemas/EnvVarSource"}, {"type": "null"}]}}, "type": "object", "required": ["name"], "title": "EnvVar"}, "EnvVarSource": {"properties": {"configMapKeyRef": {"anyOf": [{"$ref": "#/components/schemas/ConfigMapKeySelector"}, {"type": "null"}]}, "secretKeyRef": {"anyOf": [{"$ref": "#/components/schemas/SecretKeySelector"}, {"type": "null"}]}}, "type": "object", "title": "EnvVarSource"}, "HTTPValidationError": {"properties": {"detail": {"items": {"$ref": "#/components/schemas/ValidationError"}, "type": "array", "title": "Detail"}}, "type": "object", "title": "HTTPValidationError"}, "KeyToPath": {"properties": {"key": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Key"}, "path": {"type": "string", "title": "Path"}, "mode": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Mode"}}, "type": "object", "required": ["key", "path"], "title": "KeyToPath"}, "LogOpts": {"properties": {"Tail": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Tail"}, "LimitBytes": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Limitbytes"}, "Timestamps": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Timestamps"}, "Previous": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Previous"}, "SinceSeconds": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Sinceseconds"}, "SinceTime": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Sincetime"}}, "type": "object", "title": "LogOpts"}, "LogRequest": {"properties": {"Namespace": {"type": "string", "title": "Namespace"}, "PodUID": {"type": "string", "title": "Poduid"}, "PodName": {"type": "string", "title": "Podname"}, "ContainerName": {"type": "string", "title": "Containername"}, "Opts": {"$ref": "#/components/schemas/LogOpts"}}, "type": "object", "required": ["Namespace", "PodUID", "PodName", "ContainerName", "Opts"], "title": "LogRequest"}, "Metadata": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "namespace": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Namespace"}, "uid": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Uid"}, "annotations": {"anyOf": [{"additionalProperties": {"type": "string"}, "type": "object"}, {"type": "null"}], "title": "Annotations", "default": {}}, "labels": {"anyOf": [{"additionalProperties": {"type": "string"}, "type": "object"}, {"type": "null"}], "title": "Labels", "default": {}}, "generateName": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Generatename"}}, "type": "object", "title": "Metadata"}, "Pod": {"properties": {"pod": {"$ref": "#/components/schemas/PodRequest"}, "container": {"items": {"$ref": "#/components/schemas/Volume"}, "type": "array", "title": "Container"}}, "type": "object", "required": ["pod", "container"], "title": "Pod"}, "PodRequest": {"properties": {"metadata": {"$ref": "#/components/schemas/Metadata"}, "spec": {"$ref": "#/components/schemas/PodSpec"}}, "type": "object", "required": ["metadata", "spec"], "title": "PodRequest"}, "PodSpec": {"properties": {"containers": {"items": {"$ref": "#/components/schemas/Container"}, "type": "array", "title": "Containers"}, "initContainers": {"anyOf": [{"items": {"$ref": "#/components/schemas/Container"}, "type": "array"}, {"type": "null"}], "title": "Initcontainers"}, "volumes": {"anyOf": [{"items": {"$ref": "#/components/schemas/PodVolume"}, "type": "array"}, {"type": "null"}], "title": "Volumes"}, "preemptionPolicy": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Preemptionpolicy"}, "priorityClassName": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Priorityclassname"}, "priority": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Priority"}, "restartPolicy": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Restartpolicy"}, "terminationGracePeriodSeconds": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Terminationgraceperiodseconds"}}, "type": "object", "required": ["containers"], "title": "PodSpec"}, "PodStatus": {"properties": {"name": {"type": "string", "title": "Name"}, "UID": {"type": "string", "title": "Uid"}, "namespace": {"type": "string", "title": "Namespace"}, "containers": {"items": {"$ref": "#/components/schemas/ContainerStatus"}, "type": "array", "title": "Containers"}}, "type": "object", "required": ["name", "UID", "namespace", "containers"], "title": "PodStatus"}, "PodVolume": {"properties": {"name": {"type": "string", "title": "Name"}, "emptyDir": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Emptydir"}, "secret": {"anyOf": [{"$ref": "#/components/schemas/SecretVolumeSource"}, {"type": "null"}]}, "configMap": {"anyOf": [{"$ref": "#/components/schemas/ConfigMapVolumeSource"}, {"type": "null"}]}}, "type": "object", "required": ["name"], "title": "PodVolume"}, "Secret": {"properties": {"metadata": {"$ref": "#/components/schemas/Metadata"}, "data": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Data"}, "stringData": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Stringdata"}, "type": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Type"}, "immutable": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Immutable"}}, "type": "object", "required": ["metadata"], "title": "Secret"}, "SecretKeySelector": {"properties": {"key": {"type": "string", "title": "Key"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "optional": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Optional"}}, "type": "object", "required": ["key"], "title": "SecretKeySelector"}, "SecretVolumeSource": {"properties": {"secretName": {"type": "string", "title": "Secretname"}, "items": {"anyOf": [{"items": {"$ref": "#/components/schemas/KeyToPath"}, "type": "array"}, {"type": "null"}], "title": "Items", "default": []}, "optional": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Optional"}, "defaultMode": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Defaultmode"}}, "type": "object", "required": ["secretName"], "title": "SecretVolumeSource"}, "SecurityContext": {"properties": {"allowPrivilegeEscalation": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Allowprivilegeescalation"}, "privileged": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Privileged"}, "procMount": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Procmount"}, "readOnlyFileSystem": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Readonlyfilesystem"}, "runAsGroup": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Runasgroup"}, "runAsNonRoot": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Runasnonroot"}, "runAsUser": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Runasuser"}}, "type": "object", "title": "SecurityContext"}, "StateRunning": {"properties": {"startedAt": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Startedat"}}, "type": "object", "title": "StateRunning"}, "StateTerminated": {"properties": {"exitCode": {"type": "integer", "title": "Exitcode"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "required": ["exitCode"], "title": "StateTerminated"}, "StateWaiting": {"properties": {"message": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Message"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "title": "StateWaiting"}, "ValidationError": {"properties": {"loc": {"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, "type": "array", "title": "Location"}, "msg": {"type": "string", "title": "Message"}, "type": {"type": "string", "title": "Error Type"}}, "type": "object", "required": ["loc", "msg", "type"], "title": "ValidationError"}, "Volume": {"properties": {"name": {"type": "string", "title": "Name"}, "configMaps": {"anyOf": [{"items": {"$ref": "#/components/schemas/ConfigMap"}, "type": "array"}, {"type": "null"}], "title": "Configmaps"}, "secrets": {"anyOf": [{"items": {"$ref": "#/components/schemas/Secret"}, "type": "array"}, {"type": "null"}], "title": "Secrets"}, "emptyDirs": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "title": "Emptydirs"}}, "type": "object", "required": ["name"], "title": "Volume"}, "VolumeMount": {"properties": {"name": {"type": "string", "title": "Name"}, "mountPath": {"type": "string", "title": "Mountpath"}, "subPath": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Subpath"}, "readOnly": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Readonly", "default": false}, "mountPropagation": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Mountpropagation"}}, "type": "object", "required": ["name", "mountPath"], "title": "VolumeMount"}}}} \ No newline at end of file +{"openapi": "3.1.0", "info": {"title": "interLink sidecar", "description": "openapi spec for interLink apis <-> provider sidecar communication", "version": "v0.0.0"}, "paths": {"/create": {"post": {"summary": "Create Pod", "operationId": "create_pod_create_post", "requestBody": {"content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/Pod"}, "type": "array", "title": "Pod"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateStruct"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/delete": {"post": {"summary": "Delete Pod", "operationId": "delete_pod_delete_post", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/PodRequest"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "string", "title": "Response Delete Pod Delete Post"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/status": {"get": {"summary": "Status Pod", "operationId": "status_pod_status_get", "requestBody": {"content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/PodRequest"}, "type": "array", "title": "Pods"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/PodStatus"}, "type": "array", "title": "Response Status Pod Status Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/getLogs": {"get": {"summary": "Get Logs", "operationId": "get_logs_getLogs_get", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/LogRequest"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"text/plain": {"schema": {"type": "string"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}}, "components": {"schemas": {"ConfigMap": {"properties": {"metadata": {"$ref": "#/components/schemas/Metadata"}, "data": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Data"}, "binary_data": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Binary Data"}, "type": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Type"}, "immutable": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Immutable"}}, "type": "object", "required": ["metadata", "data"], "title": "ConfigMap"}, "ConfigMapKeySelector": {"properties": {"key": {"type": "string", "title": "Key"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "optional": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Optional"}}, "type": "object", "required": ["key"], "title": "ConfigMapKeySelector"}, "ConfigMapVolumeSource": {"properties": {"name": {"type": "string", "title": "Name"}, "items": {"anyOf": [{"items": {"$ref": "#/components/schemas/KeyToPath"}, "type": "array"}, {"type": "null"}], "title": "Items", "default": []}, "optional": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Optional"}, "default_mode": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Default Mode"}}, "type": "object", "required": ["name"], "title": "ConfigMapVolumeSource"}, "Container": {"properties": {"name": {"type": "string", "title": "Name"}, "image": {"type": "string", "title": "Image"}, "tag": {"type": "string", "title": "Tag", "default": "latest"}, "command": {"items": {"type": "string"}, "type": "array", "title": "Command"}, "args": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "title": "Args", "default": []}, "resources": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Resources", "default": {}}, "volume_mounts": {"anyOf": [{"items": {"$ref": "#/components/schemas/VolumeMount"}, "type": "array"}, {"type": "null"}], "title": "Volume Mounts", "default": []}, "env": {"anyOf": [{"items": {"$ref": "#/components/schemas/EnvVar"}, "type": "array"}, {"type": "null"}], "title": "Env"}, "security_context": {"anyOf": [{"$ref": "#/components/schemas/SecurityContext"}, {"type": "null"}]}}, "type": "object", "required": ["name", "image", "command"], "title": "Container"}, "ContainerStates": {"properties": {"terminated": {"anyOf": [{"$ref": "#/components/schemas/StateTerminated"}, {"type": "null"}]}, "running": {"anyOf": [{"$ref": "#/components/schemas/StateRunning"}, {"type": "null"}]}, "waiting": {"anyOf": [{"$ref": "#/components/schemas/StateWaiting"}, {"type": "null"}]}}, "type": "object", "title": "ContainerStates"}, "ContainerStatus": {"properties": {"name": {"type": "string", "title": "Name"}, "state": {"$ref": "#/components/schemas/ContainerStates"}}, "type": "object", "required": ["name", "state"], "title": "ContainerStatus"}, "CreateStruct": {"properties": {"pod_uid": {"type": "string", "title": "Pod Uid"}, "pod_jid": {"type": "string", "title": "Pod Jid"}}, "type": "object", "required": ["pod_uid", "pod_jid"], "title": "CreateStruct"}, "EnvVar": {"properties": {"name": {"type": "string", "title": "Name"}, "value": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Value"}, "value_from": {"anyOf": [{"$ref": "#/components/schemas/EnvVarSource"}, {"type": "null"}]}}, "type": "object", "required": ["name"], "title": "EnvVar"}, "EnvVarSource": {"properties": {"config_map_key_ref": {"anyOf": [{"$ref": "#/components/schemas/ConfigMapKeySelector"}, {"type": "null"}]}, "secret_key_ref": {"anyOf": [{"$ref": "#/components/schemas/SecretKeySelector"}, {"type": "null"}]}}, "type": "object", "title": "EnvVarSource"}, "HTTPValidationError": {"properties": {"detail": {"items": {"$ref": "#/components/schemas/ValidationError"}, "type": "array", "title": "Detail"}}, "type": "object", "title": "HTTPValidationError"}, "KeyToPath": {"properties": {"key": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Key"}, "path": {"type": "string", "title": "Path"}, "mode": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Mode"}}, "type": "object", "required": ["key", "path"], "title": "KeyToPath"}, "LogOpts": {"properties": {"tail": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Tail"}, "limit_bytes": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Limit Bytes"}, "timestamps": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Timestamps"}, "previous": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Previous"}, "since_seconds": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Since Seconds"}, "since_time": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Since Time"}}, "type": "object", "title": "LogOpts"}, "LogRequest": {"properties": {"namespace": {"type": "string", "title": "Namespace"}, "pod_uid": {"type": "string", "title": "Pod Uid"}, "pod_name": {"type": "string", "title": "Pod Name"}, "container_name": {"type": "string", "title": "Container Name"}, "opts": {"$ref": "#/components/schemas/LogOpts"}}, "type": "object", "required": ["namespace", "pod_uid", "pod_name", "container_name", "opts"], "title": "LogRequest"}, "Metadata": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "namespace": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Namespace"}, "uid": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Uid"}, "annotations": {"anyOf": [{"additionalProperties": {"type": "string"}, "type": "object"}, {"type": "null"}], "title": "Annotations", "default": {}}, "labels": {"anyOf": [{"additionalProperties": {"type": "string"}, "type": "object"}, {"type": "null"}], "title": "Labels", "default": {}}, "generate_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Generate Name"}}, "type": "object", "title": "Metadata"}, "Pod": {"properties": {"pod": {"$ref": "#/components/schemas/PodRequest"}, "container": {"items": {"$ref": "#/components/schemas/Volume"}, "type": "array", "title": "Container"}}, "type": "object", "required": ["pod", "container"], "title": "Pod"}, "PodRequest": {"properties": {"metadata": {"$ref": "#/components/schemas/Metadata"}, "spec": {"$ref": "#/components/schemas/PodSpec"}}, "type": "object", "required": ["metadata", "spec"], "title": "PodRequest"}, "PodSpec": {"properties": {"containers": {"items": {"$ref": "#/components/schemas/Container"}, "type": "array", "title": "Containers"}, "init_containers": {"anyOf": [{"items": {"$ref": "#/components/schemas/Container"}, "type": "array"}, {"type": "null"}], "title": "Init Containers"}, "volumes": {"anyOf": [{"items": {"$ref": "#/components/schemas/PodVolume"}, "type": "array"}, {"type": "null"}], "title": "Volumes"}, "preemption_policy": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Preemption Policy"}, "priority_class_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Priority Class Name"}, "priority": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Priority"}, "restart_policy": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Restart Policy"}, "termination_grace_period_seconds": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Termination Grace Period Seconds"}}, "type": "object", "required": ["containers"], "title": "PodSpec"}, "PodStatus": {"properties": {"name": {"type": "string", "title": "Name"}, "uid": {"type": "string", "title": "Uid"}, "namespace": {"type": "string", "title": "Namespace"}, "containers": {"items": {"$ref": "#/components/schemas/ContainerStatus"}, "type": "array", "title": "Containers"}}, "type": "object", "required": ["name", "uid", "namespace", "containers"], "title": "PodStatus"}, "PodVolume": {"properties": {"name": {"type": "string", "title": "Name"}, "empty_dir": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Empty Dir"}, "secret": {"anyOf": [{"$ref": "#/components/schemas/SecretVolumeSource"}, {"type": "null"}]}, "config_map": {"anyOf": [{"$ref": "#/components/schemas/ConfigMapVolumeSource"}, {"type": "null"}]}}, "type": "object", "required": ["name"], "title": "PodVolume"}, "Secret": {"properties": {"metadata": {"$ref": "#/components/schemas/Metadata"}, "data": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Data"}, "string_data": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "String Data"}, "type": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Type"}, "immutable": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Immutable"}}, "type": "object", "required": ["metadata"], "title": "Secret"}, "SecretKeySelector": {"properties": {"key": {"type": "string", "title": "Key"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "optional": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Optional"}}, "type": "object", "required": ["key"], "title": "SecretKeySelector"}, "SecretVolumeSource": {"properties": {"secret_name": {"type": "string", "title": "Secret Name"}, "items": {"anyOf": [{"items": {"$ref": "#/components/schemas/KeyToPath"}, "type": "array"}, {"type": "null"}], "title": "Items", "default": []}, "optional": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Optional"}, "default_mode": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Default Mode"}}, "type": "object", "required": ["secret_name"], "title": "SecretVolumeSource"}, "SecurityContext": {"properties": {"allow_privilege_escalation": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Allow Privilege Escalation"}, "privileged": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Privileged"}, "proc_mount": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Proc Mount"}, "read_only_file_system": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Read Only File System"}, "run_as_group": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Run As Group"}, "run_as_non_root": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Run As Non Root"}, "run_as_user": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Run As User"}}, "type": "object", "title": "SecurityContext"}, "StateRunning": {"properties": {"started_at": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Started At"}}, "type": "object", "title": "StateRunning"}, "StateTerminated": {"properties": {"exit_code": {"type": "integer", "title": "Exit Code"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "required": ["exit_code"], "title": "StateTerminated"}, "StateWaiting": {"properties": {"message": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Message"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "title": "StateWaiting"}, "ValidationError": {"properties": {"loc": {"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, "type": "array", "title": "Location"}, "msg": {"type": "string", "title": "Message"}, "type": {"type": "string", "title": "Error Type"}}, "type": "object", "required": ["loc", "msg", "type"], "title": "ValidationError"}, "Volume": {"properties": {"name": {"type": "string", "title": "Name"}, "config_maps": {"anyOf": [{"items": {"$ref": "#/components/schemas/ConfigMap"}, "type": "array"}, {"type": "null"}], "title": "Config Maps"}, "secrets": {"anyOf": [{"items": {"$ref": "#/components/schemas/Secret"}, "type": "array"}, {"type": "null"}], "title": "Secrets"}, "empty_dirs": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "title": "Empty Dirs"}}, "type": "object", "required": ["name"], "title": "Volume"}, "VolumeMount": {"properties": {"name": {"type": "string", "title": "Name"}, "mount_path": {"type": "string", "title": "Mount Path"}, "sub_path": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Sub Path"}, "read_only": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Read Only", "default": false}, "mount_propagation": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Mount Propagation"}}, "type": "object", "required": ["name", "mount_path"], "title": "VolumeMount"}}}} \ No newline at end of file diff --git a/example/create_openapi.py b/example/create_openapi.py index 8b11ae57..47a81b33 100644 --- a/example/create_openapi.py +++ b/example/create_openapi.py @@ -12,7 +12,7 @@ @app.post("/create") -async def create_pod(pod: interlink.Pod) -> interlink.CreateStruct: +async def create_pod(pod: List[interlink.Pod]) -> interlink.CreateStruct: raise NotImplementedError @@ -45,4 +45,4 @@ async def get_logs(req: interlink.LogRequest) -> bytes: routes=app.routes, ), f, - ) + ) \ No newline at end of file diff --git a/example/interlink/provider.py b/example/interlink/provider.py index 694254db..40378a6e 100644 --- a/example/interlink/provider.py +++ b/example/interlink/provider.py @@ -8,24 +8,24 @@ def __init__( self, docker_client, ): - self.DOCKER = docker_client - self.CONTAINER_POD_MAP = {} + self.docker = docker_client + self.container_pod_map = {} - def Create(self, pod: Pod) -> CreateStruct: + def create(self, pod: Pod) -> CreateStruct: raise HTTPException(status_code=500, detail="NOT IMPLEMENTED YET") - def Delete(self, pod: PodRequest) -> None: + def delete(self, pod: PodRequest) -> None: raise HTTPException(status_code=500, detail="NOT IMPLEMENTED YET") - def Status(self, pod: PodRequest) -> PodStatus: + def status(self, pod: PodRequest) -> PodStatus: raise HTTPException(status_code=500, detail="NOT IMPLEMENTED YET") - def Logs(self, req: LogRequest) -> bytes: + def logs(self, req: LogRequest) -> bytes: raise HTTPException(status_code=500, detail="NOT IMPLEMENTED YET") def create_pod(self, pod: Pod) -> CreateStruct: try: - self.Create(pod) + self.create(pod) except Exception as ex: raise ex @@ -33,7 +33,7 @@ def create_pod(self, pod: Pod) -> CreateStruct: def delete_pod(self, pod: PodRequest) -> str: try: - self.Delete(pod) + self.delete(pod) except Exception as ex: raise ex @@ -50,4 +50,4 @@ def get_logs(self, req: LogRequest) -> bytes: except Exception as ex: raise ex - return logContent + return logContent \ No newline at end of file diff --git a/example/interlink/spec.py b/example/interlink/spec.py index 02ecff9a..34f9a983 100644 --- a/example/interlink/spec.py +++ b/example/interlink/spec.py @@ -9,15 +9,15 @@ class Metadata(BaseModel): uid: Optional[str] = None annotations: Optional[Dict[str, str]] = Field({}) labels: Optional[Dict[str, str]] = Field({}) - generateName: Optional[str] = None + generate_name: Optional[str] = None class VolumeMount(BaseModel): name: str - mountPath: str - subPath: Optional[str] = None - readOnly: Optional[bool] = False - mountPropagation: Optional[str] = None + mount_path: str + sub_path: Optional[str] = None + read_only: Optional[bool] = False + mount_propagation: Optional[str] = None class ConfigMapKeySelector(BaseModel): @@ -33,24 +33,24 @@ class SecretKeySelector(BaseModel): class EnvVarSource(BaseModel): - configMapKeyRef: Optional[ConfigMapKeySelector] = None - secretKeyRef: Optional[SecretKeySelector] = None + config_map_key_ref: Optional[ConfigMapKeySelector] = None + secret_key_ref: Optional[SecretKeySelector] = None class EnvVar(BaseModel): name: str value: Optional[str] = None - valueFrom: Optional[EnvVarSource] = None + value_from: Optional[EnvVarSource] = None class SecurityContext(BaseModel): - allowPrivilegeEscalation: Optional[bool] = None + allow_privilege_escalation: Optional[bool] = None privileged: Optional[bool] = None - procMount: Optional[str] = None - readOnlyFileSystem: Optional[bool] = None - runAsGroup: Optional[int] = None - runAsNonRoot: Optional[bool] = None - runAsUser: Optional[int] = None + proc_mount: Optional[str] = None + read_only_file_system: Optional[bool] = None + run_as_group: Optional[int] = None + run_as_non_root: Optional[bool] = None + run_as_user: Optional[int] = None class Container(BaseModel): @@ -60,9 +60,9 @@ class Container(BaseModel): command: List[str] args: Optional[List[str]] = Field([]) resources: Optional[dict] = Field({}) - volumeMounts: Optional[List[VolumeMount]] = Field([]) + volume_mounts: Optional[List[VolumeMount]] = Field([]) env: Optional[List[EnvVar]] = None - securityContext: Optional[SecurityContext] = None + security_context: Optional[SecurityContext] = None class KeyToPath(BaseModel): @@ -72,17 +72,17 @@ class KeyToPath(BaseModel): class SecretVolumeSource(BaseModel): - secretName: str + secret_name: str items: Optional[List[KeyToPath]] = Field([]) optional: Optional[bool] = None - defaultMode: Optional[int] = None + default_mode: Optional[int] = None class ConfigMapVolumeSource(BaseModel): name: str items: Optional[List[KeyToPath]] = Field([]) optional: Optional[bool] = None - defaultMode: Optional[int] = None + default_mode: Optional[int] = None # class VolumeSource(BaseModel): @@ -94,20 +94,20 @@ class ConfigMapVolumeSource(BaseModel): class PodVolume(BaseModel): name: str # volumeSource: Optional[VolumeSource] = None - emptyDir: Optional[dict] = None + empty_dir: Optional[dict] = None secret: Optional[SecretVolumeSource] = None - configMap: Optional[ConfigMapVolumeSource] = None + config_map: Optional[ConfigMapVolumeSource] = None class PodSpec(BaseModel): containers: List[Container] - initContainers: Optional[List[Container]] = None + init_containers: Optional[List[Container]] = None volumes: Optional[List[PodVolume]] = None - preemptionPolicy: Optional[str] = None - priorityClassName: Optional[str] = None + preemption_policy: Optional[str] = None + priority_class_name: Optional[str] = None priority: Optional[int] = None - restartPolicy: Optional[str] = None - terminationGracePeriodSeconds: Optional[int] = None + restart_policy: Optional[str] = None + termination_grace_period_seconds: Optional[int] = None class PodRequest(BaseModel): @@ -118,7 +118,7 @@ class PodRequest(BaseModel): class ConfigMap(BaseModel): metadata: Metadata data: Optional[dict] - binaryData: Optional[dict] = None + binary_data: Optional[dict] = None type: Optional[str] = None immutable: Optional[bool] = None @@ -126,16 +126,16 @@ class ConfigMap(BaseModel): class Secret(BaseModel): metadata: Metadata data: Optional[dict] = None - stringData: Optional[dict] = None + string_data: Optional[dict] = None type: Optional[str] = None immutable: Optional[bool] = None class Volume(BaseModel): name: str - configMaps: Optional[List[ConfigMap]] = None + config_maps: Optional[List[ConfigMap]] = None secrets: Optional[List[Secret]] = None - emptyDirs: Optional[List[str]] = None + empty_dirs: Optional[List[str]] = None class Pod(BaseModel): @@ -144,12 +144,12 @@ class Pod(BaseModel): class StateTerminated(BaseModel): - exitCode: int + exit_code: int reason: Optional[str] = None class StateRunning(BaseModel): - startedAt: Optional[str] = None + started_at: Optional[str] = None class StateWaiting(BaseModel): @@ -170,27 +170,27 @@ class ContainerStatus(BaseModel): class PodStatus(BaseModel): name: str - UID: str + uid: str namespace: str containers: List[ContainerStatus] class LogOpts(BaseModel): - Tail: Optional[int] = None - LimitBytes: Optional[int] = None - Timestamps: Optional[bool] = None - Previous: Optional[bool] = None - SinceSeconds: Optional[int] = None - SinceTime: Optional[datetime.datetime] = None + tail: Optional[int] = None + limit_bytes: Optional[int] = None + timestamps: Optional[bool] = None + previous: Optional[bool] = None + since_seconds: Optional[int] = None + since_time: Optional[datetime.datetime] = None class LogRequest(BaseModel): - Namespace: str - PodUID: str - PodName: str - ContainerName: str - Opts: LogOpts + namespace: str + pod_uid: str + pod_name: str + container_name: str + opts: LogOpts class CreateStruct(BaseModel): - PodUID: str - PodJID: str \ No newline at end of file + pod_uid: str + pod_jid: str \ No newline at end of file diff --git a/example/provider_demo.py b/example/provider_demo.py index 5d96aa8a..83e6774a 100644 --- a/example/provider_demo.py +++ b/example/provider_demo.py @@ -8,50 +8,27 @@ import os -class MockRuntime(): - def __init__(self): - self.CONTAINERS = {} - - def create(container,cmds, args, volumes) -> str: - - print(f"image: {container.image}:{container.tag}") - print(f"command: {cmds}\nargs: {args}") - print(f"volumes: {volumes}") - print(f"env: {container.env}") - - container_id = uuid() - - self.CONTAINERS.update( - { - "id": container_id, - "start_time": now(), - "status": "Pending" - } - ) - return container_id - - def status(container_id) -> str: - return self.CONTAINERS[container_id] - - def delete(container_id) -> bool: - return true - - -#dockerCLI = docker.DockerClient() +docker_client = docker.DockerClient() # dockerCLI = docker.DockerClient(base_url="unix:///Users/dciangot/.docker/run/docker.sock") app = FastAPI() -runtime = MockRuntime() class MyProvider(interlink.provider.Provider): - def __init__(self, DOCKER): - super().__init__(DOCKER) + def __init__(self, docker): + super().__init__(docker) # Recover already running containers refs - self.CONTAINER_POD_MAP = {} - - def DumpVolumes( + self.container_pod_map = {} + statuses = self.docker.api.containers(all=True) + for status in statuses: + name = status["Names"][0] + if len(name.split("-")) > 1: + uid = "-".join(name.split("-")[-5:]) + self.container_pod_map.update({uid: [status["Id"]]}) + print(self.container_pod_map) + + def dump_volumes( self, pods: List[interlink.PodVolume], volumes: List[interlink.Volume] ) -> List[str]: @@ -59,15 +36,15 @@ def DumpVolumes( # Match data source information (actual bytes) to the mount ref in pod description for v in volumes: - if v.configMaps: - for dataSource in v.configMaps: + if v.config_maps: + for data_source in v.config_maps: for ref in pods: - podMount = ref.volumeSource.configMap - if podMount: - if ref.name == dataSource.metadata.name: - for filename, content in dataSource.data.items(): + pod_mount = ref.volume_source.config_map + if pod_mount: + if ref.name == data_source.metadata.name: + for filename, content in data_source.data.items(): # write content to file - path = f"{dataSource.metadata.namespace}-{dataSource.metadata.name}/{filename}" + path = f"{data_source.metadata.namespace}-{data_source.metadata.name}/{filename}" try: os.makedirs( os.path.dirname(path), exist_ok=True @@ -83,68 +60,84 @@ def DumpVolumes( if v.secrets: pass - if v.emptyDirs: + if v.empty_dirs: pass return dataList - def Create(self, pod: interlink.Pod) -> None: + def create(self, pod: interlink.Pod) -> None: container = pod.pod.spec.containers[0] if pod.pod.spec.volumes: - _ = self.DumpVolumes(pod.pod.spec.volumes, pod.container) + _ = self.dump_volumes(pod.pod.spec.volumes, pod.container) volumes = [] - if container.volumeMounts: - for mount in container.volumeMounts: - if mount.subPath: + if container.volume_mounts: + for mount in container.volume_mounts: + if mount.sub_path: volumes.append( - f"{pod.pod.metadata.namespace}-{mount.name}/{mount.subPath}:{mount.mountPath}" + f"{pod.pod.metadata.namespace}-{mount.name}/{mount.sub_path}:{mount.mount_path}" ) else: volumes.append( - f"{pod.pod.metadata.namespace}-{mount.name}:{mount.mountPath}" + f"{pod.pod.metadata.namespace}-{mount.name}:{mount.mount_path}" ) try: cmds = " ".join(container.command) args = " ".join(container.args) - docker_run_id = self.DOCKER.run( - container, - cmds, - args, + docker_container = self.docker.containers.run( + f"{container.image}:{container.tag}", + f"{cmds} {args}", + name=f"{container.name}-{pod.pod.metadata.uid}", + detach=True, volumes=volumes, + # runtime="nvidia", + # device_requests=[ + # docker.types.DeviceRequest(device_ids=["0"], capabilities=[['gpu']])] ) + print(docker_container) + docker_run_id = docker_container.id except Exception as ex: raise HTTPException(status_code=500, detail=ex) - self.CONTAINER_POD_MAP.update({pod.pod.metadata.uid: [docker_run_id]}) - print(self.CONTAINER_POD_MAP) + self.container_pod_map.update({pod.pod.metadata.uid: [docker_run_id]}) + print(self.container_pod_map) print(pod) - def Delete(self, pod: interlink.PodRequest) -> None: + def delete(self, pod: interlink.PodRequest) -> None: try: - print(f"docker rm -f {self.CONTAINER_POD_MAP[pod.metadata.uid][0]}") - container.remove(self.CONTAINER_POD_MAP[pod.metadata.uid][0]) - self.CONTAINER_POD_MAP.pop(pod.metadata.uid) + print(f"docker rm -f {self.container_pod_map[pod.metadata.uid][0]}") + container = self.docker.containers.get( + self.container_pod_map[pod.metadata.uid][0] + ) + container.remove(force=True) + self.container_pod_map.pop(pod.metadata.uid) except: raise HTTPException(status_code=404, detail="No containers found for UUID") + print(pod) return - def Status(self, pod: interlink.PodRequest) -> interlink.PodStatus: - print(self.CONTAINER_POD_MAP) + def status(self, pod: interlink.PodRequest) -> interlink.PodStatus: + print(self.container_pod_map) print(pod.metadata.uid) try: - status = self.DOCKER.containers.status( - self.CONTAINER_POD_MAP[pod.metadata.uid][0] + container = self.docker.containers.get( + self.container_pod_map[pod.metadata.uid][0] ) status = container.status except: raise HTTPException(status_code=404, detail="No containers found for UUID") + print(status) + if status == "running": try: - startedAt = statuses[0]["Created"] + statuses = self.docker.api.containers( + filters={"status": "running", "id": container.id} + ) + print(statuses) + started_at = statuses[0]["Created"] except Exception as ex: raise HTTPException(status_code=500, detail=ex) @@ -156,7 +149,7 @@ def Status(self, pod: interlink.PodRequest) -> interlink.PodStatus: interlink.ContainerStatus( name=pod.spec.containers[0].name, state=interlink.ContainerStates( - running=interlink.StateRunning(startedAt=startedAt), + running=interlink.StateRunning(started_at=started_at), waiting=None, terminated=None, ), @@ -166,6 +159,9 @@ def Status(self, pod: interlink.PodRequest) -> interlink.PodStatus: elif status == "exited": try: + statuses = self.docker.api.containers( + filters={"status": "exited", "id": container.id} + ) print(statuses) reason = statuses[0]["Status"] pattern = re.compile(r"Exited \((.*?)\)") @@ -215,11 +211,11 @@ def Status(self, pod: interlink.PodRequest) -> interlink.PodStatus: def Logs(self, req: interlink.LogRequest) -> bytes: # TODO: manage more complicated multi container pod # THIS IS ONLY FOR DEMONSTRATION - print(req.PodUID) - print(self.CONTAINER_POD_MAP[req.PodUID]) + print(req.pod_uid) + print(self.container_pod_map[req.pod_uid]) try: - container = self.DOCKER.containers.get( - self.CONTAINER_POD_MAP[req.PodUID][0] + container = self.docker.containers.get( + self.container_pod_map[req.pod_uid][0] ) # log = container.logs(timestamps=req.Opts.Timestamps, tail=req.Opts.Tail) log = container.logs() @@ -229,24 +225,24 @@ def Logs(self, req: interlink.LogRequest) -> bytes: return log -ProviderNew = MyProvider(MockRuntime) +provider_new = MyProvider(docker_client) @app.post("/create") async def create_pod(pods: List[interlink.Pod]) -> str: - return ProviderNew.create_pod(pods) + return provider_new.create_pod(pods) @app.post("/delete") async def delete_pod(pod: interlink.PodRequest) -> str: - return ProviderNew.delete_pod(pod) + return provider_new.delete_pod(pod) @app.get("/status") async def status_pod(pods: List[interlink.PodRequest]) -> List[interlink.PodStatus]: - return ProviderNew.get_status(pods) + return provider_new.get_status(pods) @app.get("/getLogs", response_class=PlainTextResponse) async def get_logs(req: interlink.LogRequest) -> bytes: - return ProviderNew.get_logs(req) + return provider_new.get_logs(req) \ No newline at end of file