繁体   English   中英

Kubernetes 客户端库是否包含用于验证 json/yaml 文件的 function?

[英]Does the Kubernetes client-go library contain a function for validating json/yaml files?

我想知道 Kubernetes 的客户端库是否包含验证 json/yaml 文件的 function。 理想情况下,它会捕获错误,例如名称不符合 DNS-1123 或指定的无效字段。 如果返回错误列表而不是在遇到第一个错误后返回 function,这也是理想的。

我尝试过的一个想法是执行 exec 来调用kubectl --validate --dry-run但这并不能完全验证清单(这意味着它可以通过这里但在您实际应用文件时会失败)。 它也会在第一个错误处停止。 另外,如果你有一个清单到 go 的清单,它会很快变得昂贵。

我看到的另一个选项是Kubernetes GitHub 第 193 期,但这不是真正合适的 function 也不是我正在寻找的检查。

Kubernetes 的客户端库不包含 YAML/JSON 配置文件的验证函数。

但是看看这个utiliy ,您可以在客户端使用它进行验证,也可以使用它的代码作为验证实现的示例。

您可以使用以下脚本获取k8s.io/kubernetes/pkg/apis/apps/validationk8s.io/kubernetes/pkg/apis/core/validation

#!/bin/sh
set -euo pipefail

VERSION=${1#"v"}
if [ -z "$VERSION" ]; then
    echo "Must specify version!"
    exit 1
fi
MODS=($(
    curl -sS https://raw.githubusercontent.com/kubernetes/kubernetes/v${VERSION}/go.mod |
    sed -n 's|.*k8s.io/\(.*\) => ./staging/src/k8s.io/.*|k8s.io/\1|p'
))
for MOD in "${MODS[@]}"; do
    V=$(
        go mod download -json "${MOD}@kubernetes-${VERSION}" |
        sed -n 's|.*"Version": "\(.*\)".*|\1|p'
    )
    go mod edit "-replace=${MOD}=${MOD}@${V}"
done
go get "k8s.io/kubernetes@v${VERSION}"

您可以编写这样的测试来使用ServiceDeployment验证清单:

import (
    "github.com/stretchr/testify/assert"
    appsV1 "k8s.io/api/apps/v1"
    coreV1 "k8s.io/api/core/v1"
    "k8s.io/client-go/kubernetes/scheme"
    kubernetesApps "k8s.io/kubernetes/pkg/apis/apps"
    kubernetesAppsV1 "k8s.io/kubernetes/pkg/apis/apps/v1"
    kubernetesAppsValidation "k8s.io/kubernetes/pkg/apis/apps/validation"
    kubernetesCore "k8s.io/kubernetes/pkg/apis/core"
    kubernetesCoreV1 "k8s.io/kubernetes/pkg/apis/core/v1"
    kubernetesCoreValidation "k8s.io/kubernetes/pkg/apis/core/validation"
    "strings"
    "testing"
    "text/template"
)

const RedisTemplate = `
---
apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  type: ClusterIP
  internalTrafficPolicy: Cluster
  sessionAffinity: None
  ports:
  - name: redis-port
    protocol: TCP
    port: 6379
    targetPort: 6379
--- 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
....
`

func Test_RedisManifest(t *testing.T) {
    for _, m := range strings.Split(RedisTemplate, "---") {
        if len(strings.Trim(m, "\n")) == 0 {
            continue
        }

        obj, _, err := scheme.Codecs.UniversalDeserializer().Decode([]byte(m), nil, nil)
        assert.NoError(t, err)
        assert.NotEmptyf(t, obj.GetObjectKind().GroupVersionKind().Kind, "parsed k8s object kind is empty")

        if service, ok := obj.(*coreV1.Service); ok {
            kubernetesService := &kubernetesCore.Service{}
            conversionErr := kubernetesCoreV1.Convert_v1_Service_To_core_Service(service, kubernetesService, nil)
            assert.NoError(t, conversionErr)
            kubernetesService.ObjectMeta.Namespace = "default"
            validationErrs := kubernetesCoreValidation.ValidateService(kubernetesService)
            assert.Empty(t, validationErrs)

        }

        if deployment, ok := obj.(*appsV1.Deployment); ok {
            kubernetesDeployment := &kubernetesApps.Deployment{}
            conversionErr := kubernetesAppsV1.Convert_v1_Deployment_To_apps_Deployment(deployment, kubernetesDeployment, nil)
            assert.NoError(t, conversionErr)

            kubernetesDeployment.ObjectMeta.Namespace = "default"
            validationErrs := kubernetesAppsValidation.ValidateDeployment(kubernetesDeployment, kubernetesCoreValidation.PodValidationOptions{})
            assert.Empty(t, validationErrs)
        }
    }
}

我在这种方法中看到以下缺点:

  1. K8s 团队不建议直接导入k8s.io/kubernetes
  2. 直接导入k8s.io/kubernetes会很麻烦。
  3. Valdation 函数ValidateServiceValidateDeployment期望可选字段,如namespaceinternalTrafficPolicysessionAffinity和许多其他字段必须具有值。 也许还有其他一些函数可以用默认值填充可选字段,但我目前还没有找到它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM