kubesphere / ksbuilder

A CLI tool helps you to manage the development of kubesphere extensions
MIT License
10 stars 19 forks source link

unmarshal the extension metadata failed: error converting YAML to JSON: yaml: control characters are not allowed #84

Closed stoneshi-yunify closed 4 months ago

stoneshi-yunify commented 4 months ago

一个非常诡异的事件。with ksbuilder 0.3.9 & 0.3.8

一个开发者提交了一个extension包,需要上架到kubesphere.com.cn 的应用市场。

我解压安装包,看到extension.yaml 引用了static 目录中的图片,就把static 中的图片都上传到s3了。然后更改了extension.yaml 中的screenshots和icon 字段,如下:

screenshots:
- https://ks-extension.pek3b.qingstor.com/extensions/arksec-redstone/0.jpg
- https://ks-extension.pek3b.qingstor.com/extensions/arksec-redstone/1.jpg
- https://ks-extension.pek3b.qingstor.com/extensions/arksec-redstone/2.jpg
- https://ks-extension.pek3b.qingstor.com/extensions/arksec-redstone/3.jpg
- https://ks-extension.pek3b.qingstor.com/extensions/arksec-redstone/4.jpg
- https://ks-extension.pek3b.qingstor.com/extensions/arksec-redstone/5.jpg
icon: https://ks-extension.pek3b.qingstor.com/extensions/arksec-redstone/arksec.png

之后删除了static中的所有文件。然后执行

ksbuilder package arksec-redstone

成功打包出一个新的 arksec-redstone-2.15.7.tgz, 然后将这个包上传到cloud。

上传时,cloud 会调用 ksbuilder 的 ValidateExtension 方法, 这个方法报错:

unmarshal the extension metadata failed: error converting YAML to JSON: yaml: control characters are not allowed

the original package: old-arksec-redstone-2.15.7.tgz

the new package (with picture links): arksec-redstone-2.15.7.tgz

我本地使用如下代码测试了下,错误一样:

package main

import (
    "os"

    "github.com/kubesphere/ksbuilder/pkg/extension"
    "github.com/kubesphere/ksbuilder/pkg/parser"
    "k8s.io/klog/v2"
    "sigs.k8s.io/yaml"
)

func do(name string, path string) error {
    klog.Info(name, path)
    tgz, err := os.ReadFile(path)
    if err != nil {
        return err

    }
    err = parser.ValidateExtension(name, tgz)
    return err
}

func main() {
    var err error

    // old package
    err = do("arksec-redstone", "/Users/stone/Downloads/aa/old-arksec-redstone-2.15.7.tgz")
    if err != nil {
        klog.Error(err)
    } else {
        klog.Info("ok")
    }

    // new package
    err = do("arksec-redstone", "/Users/stone/Downloads/bb/arksec-redstone-2.15.7.tgz")
    if err != nil {
        klog.Error(err)
    } else {
        klog.Info("ok")
    }
}

输出:

I0302 18:24:20.878791   91206 main.go:13] arksec-redstone/Users/stone/Downloads/aa/old-arksec-redstone-2.15.7.tgz
I0302 18:24:47.499887   91206 main.go:65] ok
I0302 18:24:47.499908   91206 main.go:13] arksec-redstone/Users/stone/Downloads/bb/arksec-redstone-2.15.7.tgz
E0302 18:26:41.924178   91206 main.go:71] unmarshal the extension metadata failed: error converting YAML to JSON: yaml: control characters are not allowed
Exiting.

打了断点,进入validateextension 方法,发现获得的 extension.yaml 的 buffer 里确实有很多 NUL 字符,所以报错了。old package 里解析到的buffer 里没有 NUL 字符串。

Screenshot 2024-03-02 at 18 25 03 Screenshot 2024-03-02 at 18 25 07

这表明new package 中的extension.yaml 有问题,不能解析。

但奇怪的是,如果把new package 在本地解压,直接用yaml.unmarshal 解析其中的extension.yaml ,并不会出错。这说明错误发生在 validateextension 的过程中。

我怀疑触发了这个bug: Screenshot 2024-03-02 at 18 33 52

如果把 这里的代码 换成这样就没问题了:

        buffer := bytes.NewBuffer([]byte{})
        //buffer := make([]byte, h.Size)
        if _, err = io.Copy(buffer, tr); err != nil && err != io.EOF {
            return fmt.Errorf("read tar file failed: %s", err.Error())
        }
        metadata := new(extension.Metadata)
        if err = yaml.Unmarshal(buffer.Bytes(), metadata); err != nil {
            return fmt.Errorf("unmarshal the extension metadata failed: %s", err.Error())
        }

麻烦你也在本地试一下,是否也有这个问题。