From 41c385066d61d3cf9e7910c1532cc75beb8a1dcb Mon Sep 17 00:00:00 2001 From: chantu Date: Tue, 7 Nov 2023 14:51:24 +0800 Subject: [PATCH] cherry-pick from 0e19ca8fc03be81028bb80f2807b1f1f30c87808 and update xinference cpu image version --- Makefile | 2 + apis/apps/v1alpha1/zz_generated.deepcopy.go | 5 +- .../v1alpha1/zz_generated.deepcopy.go | 2 +- .../v1alpha1/zz_generated.deepcopy.go | 2 +- .../storage/v1alpha1/zz_generated.deepcopy.go | 2 +- .../v1alpha1/zz_generated.deepcopy.go | 2 +- .../templates/addons/xinference-addon.yaml | 30 +++++++++ deploy/xinference-cluster/.helmignore | 24 ++++++++ deploy/xinference-cluster/Chart.yaml | 27 ++++++++ deploy/xinference-cluster/templates/NOTES.txt | 2 + .../xinference-cluster/templates/_helpers.tpl | 3 + .../xinference-cluster/templates/cluster.yaml | 20 ++++++ deploy/xinference-cluster/templates/rbac.yaml | 1 + .../templates/validate.yaml | 12 ++++ deploy/xinference-cluster/values.schema.json | 61 +++++++++++++++++++ deploy/xinference-cluster/values.yaml | 27 ++++++++ deploy/xinference/Chart.yaml | 24 ++++++++ deploy/xinference/templates/NOTES.txt | 0 deploy/xinference/templates/_helpers.tpl | 33 ++++++++++ .../templates/clusterdefinition.yaml | 43 +++++++++++++ .../xinference/templates/clusterversion.yaml | 43 +++++++++++++ deploy/xinference/templates/scripts.yaml | 10 +++ deploy/xinference/values.yaml | 7 +++ docs/user_docs/cli/kbcli_cluster_create.md | 1 + .../v1beta2/zz_generated.deepcopy.go | 2 +- pkg/cli/cluster/builtin_charts.go | 21 +++++++ 26 files changed, 399 insertions(+), 7 deletions(-) create mode 100644 deploy/helm/templates/addons/xinference-addon.yaml create mode 100644 deploy/xinference-cluster/.helmignore create mode 100644 deploy/xinference-cluster/Chart.yaml create mode 100644 deploy/xinference-cluster/templates/NOTES.txt create mode 100644 deploy/xinference-cluster/templates/_helpers.tpl create mode 100644 deploy/xinference-cluster/templates/cluster.yaml create mode 100644 deploy/xinference-cluster/templates/rbac.yaml create mode 100644 deploy/xinference-cluster/templates/validate.yaml create mode 100644 deploy/xinference-cluster/values.schema.json create mode 100644 deploy/xinference-cluster/values.yaml create mode 100644 deploy/xinference/Chart.yaml create mode 100644 deploy/xinference/templates/NOTES.txt create mode 100644 deploy/xinference/templates/_helpers.tpl create mode 100644 deploy/xinference/templates/clusterdefinition.yaml create mode 100644 deploy/xinference/templates/clusterversion.yaml create mode 100644 deploy/xinference/templates/scripts.yaml create mode 100644 deploy/xinference/values.yaml diff --git a/Makefile b/Makefile index c34c5478602..3ee6486a146 100644 --- a/Makefile +++ b/Makefile @@ -302,6 +302,8 @@ build-kbcli-embed-chart: helmtool create-kbcli-embed-charts-dir \ build-single-kbcli-embed-chart.postgresql-cluster \ build-single-kbcli-embed-chart.kafka-cluster \ build-single-kbcli-embed-chart.mongodb-cluster \ + build-single-kbcli-embed-chart.llm-cluster \ + build-single-kbcli-embed-chart.xinference-cluster \ # build-single-kbcli-embed-chart.neon-cluster # build-single-kbcli-embed-chart.postgresql-cluster \ # build-single-kbcli-embed-chart.clickhouse-cluster \ diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index b1a33d850ad..2116a9c24cc 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -25,13 +25,14 @@ along with this program. If not, see . package v1alpha1 import ( - workloadsv1alpha1 "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" appsv1 "k8s.io/api/apps/v1" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" + + workloadsv1alpha1 "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. diff --git a/apis/dataprotection/v1alpha1/zz_generated.deepcopy.go b/apis/dataprotection/v1alpha1/zz_generated.deepcopy.go index 06449f5aa3a..5f955a82a32 100644 --- a/apis/dataprotection/v1alpha1/zz_generated.deepcopy.go +++ b/apis/dataprotection/v1alpha1/zz_generated.deepcopy.go @@ -25,7 +25,7 @@ along with this program. If not, see . package v1alpha1 import ( - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) diff --git a/apis/extensions/v1alpha1/zz_generated.deepcopy.go b/apis/extensions/v1alpha1/zz_generated.deepcopy.go index dc6dc6af55e..eeec9922d51 100644 --- a/apis/extensions/v1alpha1/zz_generated.deepcopy.go +++ b/apis/extensions/v1alpha1/zz_generated.deepcopy.go @@ -26,7 +26,7 @@ package v1alpha1 import ( corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) diff --git a/apis/storage/v1alpha1/zz_generated.deepcopy.go b/apis/storage/v1alpha1/zz_generated.deepcopy.go index f22b9440108..0ab972c839a 100644 --- a/apis/storage/v1alpha1/zz_generated.deepcopy.go +++ b/apis/storage/v1alpha1/zz_generated.deepcopy.go @@ -25,7 +25,7 @@ along with this program. If not, see . package v1alpha1 import ( - "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) diff --git a/apis/workloads/v1alpha1/zz_generated.deepcopy.go b/apis/workloads/v1alpha1/zz_generated.deepcopy.go index f2a4dfdf03d..34e7c5f1212 100644 --- a/apis/workloads/v1alpha1/zz_generated.deepcopy.go +++ b/apis/workloads/v1alpha1/zz_generated.deepcopy.go @@ -26,7 +26,7 @@ package v1alpha1 import ( corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) diff --git a/deploy/helm/templates/addons/xinference-addon.yaml b/deploy/helm/templates/addons/xinference-addon.yaml new file mode 100644 index 00000000000..970205b5676 --- /dev/null +++ b/deploy/helm/templates/addons/xinference-addon.yaml @@ -0,0 +1,30 @@ +apiVersion: extensions.kubeblocks.io/v1alpha1 +kind: Addon +metadata: + name: xinference + labels: + {{- include "kubeblocks.labels" . | nindent 4 }} + "kubeblocks.io/provider": community + {{- if .Values.keepAddons }} + annotations: + helm.sh/resource-policy: keep + {{- end }} +spec: + description: 'xinference' + + type: Helm + + helm: + {{- include "kubeblocks.addonChartLocationURL" ( dict "name" "xinference" "version" (default .Chart.Version .Values.versionOverride) "values" .Values) | indent 4 }} + {{- include "kubeblocks.addonChartsImage" . | indent 4 }} + + installOptions: + {{- if hasPrefix "oci://" .Values.addonChartLocationBase }} + version: {{ default .Chart.Version .Values.versionOverride }} + {{- end }} + + installable: + autoInstall: false + + defaultInstallValues: + - enabled: false diff --git a/deploy/xinference-cluster/.helmignore b/deploy/xinference-cluster/.helmignore new file mode 100644 index 00000000000..a2391b0ad18 --- /dev/null +++ b/deploy/xinference-cluster/.helmignore @@ -0,0 +1,24 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +*.lock diff --git a/deploy/xinference-cluster/Chart.yaml b/deploy/xinference-cluster/Chart.yaml new file mode 100644 index 00000000000..b1131e634eb --- /dev/null +++ b/deploy/xinference-cluster/Chart.yaml @@ -0,0 +1,27 @@ +annotations: + category: Database +apiVersion: v2 +name: xinference-cluster +type: application +version: 0.7.0-alpha.0 +description: A vxinference Cluster Helm chart for KubeBlocks. +dependencies: + - name: kblib + version: 0.1.0 + repository: file://../kblib + alias: extra + +appVersion: "7.0.6" + +keywords: + - xinference + +home: https://github.com/apecloud/kubeblocks/tree/main/deploy/xinference-cluster +icon: https://kubeblocks.io/img/logo.png + +maintainers: + - name: ApeCloud + url: https://kubeblocks.io/ + +sources: + - https://github.com/apecloud/kubeblocks/ \ No newline at end of file diff --git a/deploy/xinference-cluster/templates/NOTES.txt b/deploy/xinference-cluster/templates/NOTES.txt new file mode 100644 index 00000000000..c3b3453e34b --- /dev/null +++ b/deploy/xinference-cluster/templates/NOTES.txt @@ -0,0 +1,2 @@ +1. Get the application URL by running these commands: + diff --git a/deploy/xinference-cluster/templates/_helpers.tpl b/deploy/xinference-cluster/templates/_helpers.tpl new file mode 100644 index 00000000000..aa4729c9b5b --- /dev/null +++ b/deploy/xinference-cluster/templates/_helpers.tpl @@ -0,0 +1,3 @@ +{{/* +Define xinference cluster component. +*/}} diff --git a/deploy/xinference-cluster/templates/cluster.yaml b/deploy/xinference-cluster/templates/cluster.yaml new file mode 100644 index 00000000000..dad55419439 --- /dev/null +++ b/deploy/xinference-cluster/templates/cluster.yaml @@ -0,0 +1,20 @@ +{{- include "kblib.clusterCommon" . }} + clusterDefinitionRef: xinference # ref clusterDefinition.name + {{ if .Values.cpuMode }} + clusterVersionRef: {{ .Values.cpuVersion }} + {{ end }} + componentSpecs: + - name: xinference + componentDefRef: xinference # ref clusterDefinition componentDefs.name + {{- include "kblib.componentMonitor" . | indent 6 }} + replicas: {{ .Values.replicas }} + serviceAccountName: {{ include "kblib.serviceAccountName" . }} + {{ if .Values.cpuMode }} + {{- include "kblib.componentResources" . | indent 6 }} + {{ else }} + resources: + limits: + nvidia.com/gpu: {{ .Values.gpu }} + requests: + nvidia.com/gpu: {{ .Values.gpu }} + {{ end }} diff --git a/deploy/xinference-cluster/templates/rbac.yaml b/deploy/xinference-cluster/templates/rbac.yaml new file mode 100644 index 00000000000..08875e8bf00 --- /dev/null +++ b/deploy/xinference-cluster/templates/rbac.yaml @@ -0,0 +1 @@ +{{- include "kblib.rbac" . }} \ No newline at end of file diff --git a/deploy/xinference-cluster/templates/validate.yaml b/deploy/xinference-cluster/templates/validate.yaml new file mode 100644 index 00000000000..0af63b61566 --- /dev/null +++ b/deploy/xinference-cluster/templates/validate.yaml @@ -0,0 +1,12 @@ +{{/* +Validate cpu, memory and storage +*/}} +{{- $cpu := (float64 .Values.cpu) }} +{{- $memory := (float64 .Values.memory) }} +{{- $storage := (float64 .Values.storage) }} +{{- if or (lt $cpu 0.5) (gt $cpu 64.0) }} +{{- fail (print "cpu must be between 0.5 and 64, got " $cpu) }} +{{- end }} +{{- if or (lt $memory 0.5) (gt $memory 1000.0) }} +{{- fail (print "memory must be between 0.5 and 1000, got " $memory) }} +{{- end }} \ No newline at end of file diff --git a/deploy/xinference-cluster/values.schema.json b/deploy/xinference-cluster/values.schema.json new file mode 100644 index 00000000000..4dd3468d7ac --- /dev/null +++ b/deploy/xinference-cluster/values.schema.json @@ -0,0 +1,61 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "cpuMode": { + "title": "CPU Mode", + "description": "Set to true if no GPU is available", + "type": "boolean", + "default": false + }, + "version": { + "title": "Version", + "description": "Cluster version.", + "type": "string", + "default": "xinference-latest" + }, + "replicas": { + "title": "Replicas", + "description": "The number of replicas, for standalone mode, the replicas is 1, for replication mode, the default replicas is 2.", + "type": "integer", + "default": 1, + "minimum": 1, + "maximum": 5 + }, + "cpu": { + "title": "CPU", + "description": "CPU cores.", + "type": [ + "number", + "string" + ], + "default": 2, + "minimum": 0.5, + "maximum": 64, + "multipleOf": 0.5 + }, + "memory": { + "title": "Memory(Gi)", + "description": "Memory, the unit is Gi.", + "type": [ + "number", + "string" + ], + "default": 6, + "minimum": 0.5, + "maximum": 1000 + }, + "gpu": { + "title": "GPU", + "description": "GPU cores.", + "type": [ + "number", + "string" + ], + "default": 1, + "minimum": 0, + "maximum": 64, + "multipleOf": 1 + } + } +} diff --git a/deploy/xinference-cluster/values.yaml b/deploy/xinference-cluster/values.yaml new file mode 100644 index 00000000000..9e73b075ae4 --- /dev/null +++ b/deploy/xinference-cluster/values.yaml @@ -0,0 +1,27 @@ +# Default values for xinference-cluster. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +## @param version xinference cluster version +## +version: xinference-latest + +cpuVersion: xinference-cpu-latest + +## @param replicas specify cluster replicas +## +replicas: 1 + +## @param cpu +## +cpu: 3 + +## @param memory, the unit is Gi +## +memory: 7 + +## @param gpu +## +gpu: 1 + +cpuMode: false \ No newline at end of file diff --git a/deploy/xinference/Chart.yaml b/deploy/xinference/Chart.yaml new file mode 100644 index 00000000000..8d299d956df --- /dev/null +++ b/deploy/xinference/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: xinference +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" \ No newline at end of file diff --git a/deploy/xinference/templates/NOTES.txt b/deploy/xinference/templates/NOTES.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/deploy/xinference/templates/_helpers.tpl b/deploy/xinference/templates/_helpers.tpl new file mode 100644 index 00000000000..e79553b35f2 --- /dev/null +++ b/deploy/xinference/templates/_helpers.tpl @@ -0,0 +1,33 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "xinference.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "xinference.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "xinference.labels" -}} +helm.sh/chart: {{ include "xinference.chart" . }} +{{ include "xinference.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "xinference.selectorLabels" -}} +app.kubernetes.io/name: {{ include "xinference.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/deploy/xinference/templates/clusterdefinition.yaml b/deploy/xinference/templates/clusterdefinition.yaml new file mode 100644 index 00000000000..e04525425b0 --- /dev/null +++ b/deploy/xinference/templates/clusterdefinition.yaml @@ -0,0 +1,43 @@ +apiVersion: apps.kubeblocks.io/v1alpha1 +kind: ClusterDefinition +metadata: + name: xinference + labels: + {{- include "xinference.labels" . | nindent 4}} +spec: + componentDefs: + - name: xinference + workloadType: Stateful + characterType: xinference + scriptSpecs: + - name: xinference-scripts + templateRef: xinference-scripts + namespace: {{ .Release.Namespace }} + volumeName: scripts + defaultMode: 493 + service: + ports: + - name: xinference + port: 9997 + targetPort: xinference + podSpec: + containers: + - name: xinference + imagePullPolicy: {{default .Values.image.pullPolicy "IfNotPresent"}} + securityContext: + runAsUser: 0 + privileged: true + allowPrivilegeEscalation: true + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - name: scripts + mountPath: /scripts + command: + - /scripts/start.sh + ports: + - name: xinference + containerPort: 9997 + connectionCredential: + username: root + password: "" diff --git a/deploy/xinference/templates/clusterversion.yaml b/deploy/xinference/templates/clusterversion.yaml new file mode 100644 index 00000000000..f0221113bb2 --- /dev/null +++ b/deploy/xinference/templates/clusterversion.yaml @@ -0,0 +1,43 @@ +apiVersion: apps.kubeblocks.io/v1alpha1 +kind: ClusterVersion +metadata: + name: xinference-latest + labels: + {{- include "xinference.labels" . | nindent 4 }} + annotations: + kubeblocks.io/is-default-cluster-version: "true" +spec: + clusterDefinitionRef: xinference + componentVersions: + - componentDefRef: xinference + versionsContext: + containers: + - name: xinference + image: {{ .Values.image.registry | default "docker.io" }}/{{ .Values.image.repository}}:{{ default .Chart.AppVersion .Values.image.tag }} +--- +apiVersion: apps.kubeblocks.io/v1alpha1 +kind: ClusterVersion +metadata: + name: xinference-cpu-latest + labels: + {{- include "xinference.labels" . | nindent 4 }} +spec: + clusterDefinitionRef: xinference + componentVersions: + - componentDefRef: xinference + versionsContext: + initContainers: + - name: download + image: infracreate-registry.cn-zhangjiakou.cr.aliyuncs.com/apecloud/baichuan2-7b-gguf:ggml-model-q4 + command: ["sh", "-c", "cp /models/ggml-model-q4.gguf /models-target/"] + volumeMounts: + - name: models + mountPath: /models-target + containers: + - name: xinference + image: docker.io/apecloud/xinference:latest-cpu + volumeMounts: + - name: models + mountPath: /models + - name: scripts + mountPath: /scripts diff --git a/deploy/xinference/templates/scripts.yaml b/deploy/xinference/templates/scripts.yaml new file mode 100644 index 00000000000..2ee6b3e386a --- /dev/null +++ b/deploy/xinference/templates/scripts.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: xinference-scripts + labels: + {{- include "xinference.labels" . | nindent 4 }} +data: + start.sh: | + #!/bin/bash + xinference --host 0.0.0.0 \ No newline at end of file diff --git a/deploy/xinference/values.yaml b/deploy/xinference/values.yaml new file mode 100644 index 00000000000..f471b35cae4 --- /dev/null +++ b/deploy/xinference/values.yaml @@ -0,0 +1,7 @@ +image: + repository: apecloud/xinference + pullPolicy: IfNotPresent + # registry: infracreate-registry.cn-zhangjiakou.cr.aliyuncs.com + registry: docker.io + # Overrides the image tag whose default is the chart appVersion. + tag: latest-amd64 \ No newline at end of file diff --git a/docs/user_docs/cli/kbcli_cluster_create.md b/docs/user_docs/cli/kbcli_cluster_create.md index 92372f0a639..db4dc89c96e 100644 --- a/docs/user_docs/cli/kbcli_cluster_create.md +++ b/docs/user_docs/cli/kbcli_cluster_create.md @@ -161,6 +161,7 @@ kbcli cluster create [NAME] [flags] * [kbcli cluster create mysql](kbcli_cluster_create_mysql.md) - Create a mysql cluster. * [kbcli cluster create postgresql](kbcli_cluster_create_postgresql.md) - Create a postgresql cluster. * [kbcli cluster create redis](kbcli_cluster_create_redis.md) - Create a redis cluster. +* [kbcli cluster create xinference](kbcli_cluster_create_xinference.md) - Create a xinference cluster. #### Go Back to [CLI Overview](cli.md) Homepage. diff --git a/externalapis/preflight/v1beta2/zz_generated.deepcopy.go b/externalapis/preflight/v1beta2/zz_generated.deepcopy.go index e1cbcb93528..395b99094bf 100644 --- a/externalapis/preflight/v1beta2/zz_generated.deepcopy.go +++ b/externalapis/preflight/v1beta2/zz_generated.deepcopy.go @@ -26,7 +26,7 @@ package v1beta2 import ( troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) diff --git a/pkg/cli/cluster/builtin_charts.go b/pkg/cli/cluster/builtin_charts.go index 6014f99ee78..0d0fe724696 100644 --- a/pkg/cli/cluster/builtin_charts.go +++ b/pkg/cli/cluster/builtin_charts.go @@ -68,6 +68,10 @@ var ( redisChart embed.FS //go:embed charts/mongodb-cluster.tgz mongodbChart embed.FS + //go:embed charts/llm-cluster.tgz + llmChart embed.FS + //go:embed charts/xinference-cluster.tgz + xinferenceChart embed.FS ) func IsbuiltinCharts(chart string) bool { @@ -123,4 +127,21 @@ func init() { fmt.Println(err.Error()) } + llm := &embedConfig{ + chartFS: llmChart, + name: "llm-cluster.tgz", + alias: "", + } + if err := llm.register("llm"); err != nil { + fmt.Println(err.Error()) + } + + xinference := &embedConfig{ + chartFS: xinferenceChart, + name: "xinference-cluster.tgz", + alias: "", + } + if err := xinference.register("xinference"); err != nil { + fmt.Println(err.Error()) + } }