From a93ea35ad4386dcf86407ce0aab88312db3b09f7 Mon Sep 17 00:00:00 2001 From: zongz Date: Mon, 18 Mar 2024 22:28:38 +0800 Subject: [PATCH 1/2] feat: support import in krm-function Signed-off-by: zongz --- .../web-service-with-import/main.k | 46 +++++++++++++++++ .../web-service-with-import/schemas.k | 51 +++++++++++++++++++ .../web-service-with-import/suite/config.yaml | 20 ++++++++ .../web-service-with-import/suite/good.yaml | 23 +++++++++ pkg/source/api.go | 4 +- pkg/source/local.go | 25 +++++++++ 6 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 examples/abstraction/web-service-with-import/main.k create mode 100644 examples/abstraction/web-service-with-import/schemas.k create mode 100644 examples/abstraction/web-service-with-import/suite/config.yaml create mode 100644 examples/abstraction/web-service-with-import/suite/good.yaml diff --git a/examples/abstraction/web-service-with-import/main.k b/examples/abstraction/web-service-with-import/main.k new file mode 100644 index 0000000..734c39f --- /dev/null +++ b/examples/abstraction/web-service-with-import/main.k @@ -0,0 +1,46 @@ +import schemas as s + +# Convert the `App` model into Kubernetes Deployment and Service Manifests +kubernetesRender = lambda a: s.App { + # Construct the deployment manifest. + deployment = { + apiVersion = "apps/v1" + kind = "Deployment" + metadata.name = a.name + metadata.labels = a.labels + spec = { + replicas = a.replicas + selector.matchLabels = a.labels + template.metadata.labels = a.labels + template.spec.containers = [ + { + name = name + image = c.image + command = c.command + args = c.args + env = c.env + volumeMounts = c.volumes + resources: c.resources + ports = c.ports + } for name, c in a.containers + ] + } + } + # Construct the service manifest. + service = { + apiVersion = "v1" + kind = "Service" + metadata.name = a.name + metadata.labels = a.labels + spec = { + type = a.service?.$type + selector = a.labels + ports = a.service?.ports + } + } + # Returns Kubernetes manifests + [deployment, if a.service: service] +} + +params: s.App = option("params") +items = kubernetesRender(params) diff --git a/examples/abstraction/web-service-with-import/schemas.k b/examples/abstraction/web-service-with-import/schemas.k new file mode 100644 index 0000000..28a8aed --- /dev/null +++ b/examples/abstraction/web-service-with-import/schemas.k @@ -0,0 +1,51 @@ +schema App: + """The application model.""" + name: str + replicas: int = 1 + labels?: {str:str} = {app = name} + service?: Service + containers?: {str: Container} + +schema Service: + """The service model.""" + $type?: str + ports: [Port] + +schema Port: + """The port model.""" + port: int + protocol: "TCP" | "UDP" | "SCTP" = "TCP" + targetPort?: int | str + +schema Container: + """The container model.""" + image: str + command?: [str] + args?: [str] + env?: [Env] + volumes?: [Volume] + resources?: Resource + ports: [ContainerPort] + +schema ContainerPort: + """The container port model.""" + name?: str + protocol: "TCP" | "UDP" | "SCTP" = "TCP" + containerPort: int + + check: + 1 <= containerPort <= 65535, "containerPort must be between 1 and 65535, inclusive" + +schema Env: + name: str + value: str + +schema Volume: + source: str + path: str + target: str + readOnly?: bool = False + +schema Resource: + limits?: {str:} + requests?: {str:} diff --git a/examples/abstraction/web-service-with-import/suite/config.yaml b/examples/abstraction/web-service-with-import/suite/config.yaml new file mode 100644 index 0000000..5c65bb4 --- /dev/null +++ b/examples/abstraction/web-service-with-import/suite/config.yaml @@ -0,0 +1,20 @@ +apiVersion: config.kubernetes.io/v1 +kind: ResourceList +items: +functionConfig: + apiVersion: krm.kcl.dev/v1alpha1 + kind: KCLRun + spec: + params: + name: app + containers: + nginx: + image: nginx + ports: + - containerPort: 80 + service: + ports: + - port: 80 + labels: + name: app + source: oci://ghcr.io/kcl-lang/web-service diff --git a/examples/abstraction/web-service-with-import/suite/good.yaml b/examples/abstraction/web-service-with-import/suite/good.yaml new file mode 100644 index 0000000..cd9effb --- /dev/null +++ b/examples/abstraction/web-service-with-import/suite/good.yaml @@ -0,0 +1,23 @@ +apiVersion: krm.kcl.dev/v1alpha1 +kind: KCLRun +metadata: + name: web-service + annotations: + krm.kcl.dev/version: 0.0.1 + krm.kcl.dev/type: abstraction + documentation: >- + Web service application abstraction +spec: + params: + name: app + containers: + nginx: + image: nginx + ports: + - containerPort: 80 + service: + ports: + - port: 80 + labels: + name: app + source: ./examples/abstraction/web-service-with-import/main.k diff --git a/pkg/source/api.go b/pkg/source/api.go index e4b1b47..f456242 100644 --- a/pkg/source/api.go +++ b/pkg/source/api.go @@ -10,7 +10,9 @@ func LocaleSource(src string) (string, error) { if IsOCI(src) { // Read code from a OCI source. return ReadFromOCISource(src) - } else if IsLocal(src) || IsRemoteUrl(src) || IsGit(src) || IsVCSDomain(src) { + } else if IsLocal(src) { + return ReadFromLocalSource(src) + } else if IsRemoteUrl(src) || IsGit(src) || IsVCSDomain(src) { // Read code from local path or a remote url. return ReadThroughGetter(src) } else { diff --git a/pkg/source/local.go b/pkg/source/local.go index d9217fd..40b2912 100644 --- a/pkg/source/local.go +++ b/pkg/source/local.go @@ -3,6 +3,9 @@ package source import ( "path/filepath" "strings" + + kpmreporter "kcl-lang.io/kpm/pkg/reporter" + kpmrunner "kcl-lang.io/kpm/pkg/runner" ) // IsLocal determines whether or not a source is to be treated as a local path. @@ -12,3 +15,25 @@ func IsLocal(src string) bool { } return false } + +// ReadFromOCISource reads source code from an OCI (Open Container Initiative) source. +// +// Parameters: +// - src: a string containing the OCI source URL. +// +// Return: +// A string containing the source code, and an error if any. +func ReadFromLocalSource(src string) (string, error) { + // Find the mod root + + modpath, kpmerr := kpmrunner.FindModRootFrom(src) + if kpmerr != nil { + if kpmerr.Type() != kpmreporter.KclModNotFound { + return "", kpmerr + } else { + modpath = filepath.Dir(src) + } + } + + return GetSourceFromDir(modpath) +} From 1926ca4470de83c8e73ec3d31a498908eecd9bae Mon Sep 17 00:00:00 2001 From: zongz Date: Tue, 19 Mar 2024 11:09:16 +0800 Subject: [PATCH 2/2] fix: fix comments and import alias Signed-off-by: zongz --- pkg/source/local.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/source/local.go b/pkg/source/local.go index 40b2912..c6cda09 100644 --- a/pkg/source/local.go +++ b/pkg/source/local.go @@ -4,8 +4,8 @@ import ( "path/filepath" "strings" - kpmreporter "kcl-lang.io/kpm/pkg/reporter" - kpmrunner "kcl-lang.io/kpm/pkg/runner" + "kcl-lang.io/kpm/pkg/reporter" + "kcl-lang.io/kpm/pkg/runner" ) // IsLocal determines whether or not a source is to be treated as a local path. @@ -16,19 +16,19 @@ func IsLocal(src string) bool { return false } -// ReadFromOCISource reads source code from an OCI (Open Container Initiative) source. +// ReadFromLocalSource reads source code from a local file system path source. // // Parameters: -// - src: a string containing the OCI source URL. +// - src: a local file system path. // // Return: // A string containing the source code, and an error if any. func ReadFromLocalSource(src string) (string, error) { // Find the mod root - modpath, kpmerr := kpmrunner.FindModRootFrom(src) + modpath, kpmerr := runner.FindModRootFrom(src) if kpmerr != nil { - if kpmerr.Type() != kpmreporter.KclModNotFound { + if kpmerr.Type() != reporter.KclModNotFound { return "", kpmerr } else { modpath = filepath.Dir(src)