code.gitea.io/gitea@v1.19.3/modules/packages/helm/metadata.go (about) 1 // Copyright 2022 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package helm 5 6 import ( 7 "archive/tar" 8 "compress/gzip" 9 "io" 10 "strings" 11 12 "code.gitea.io/gitea/modules/util" 13 "code.gitea.io/gitea/modules/validation" 14 15 "github.com/hashicorp/go-version" 16 "gopkg.in/yaml.v3" 17 ) 18 19 var ( 20 // ErrMissingChartFile indicates a missing Chart.yaml file 21 ErrMissingChartFile = util.NewInvalidArgumentErrorf("Chart.yaml file is missing") 22 // ErrInvalidName indicates an invalid package name 23 ErrInvalidName = util.NewInvalidArgumentErrorf("package name is invalid") 24 // ErrInvalidVersion indicates an invalid package version 25 ErrInvalidVersion = util.NewInvalidArgumentErrorf("package version is invalid") 26 // ErrInvalidChart indicates an invalid chart 27 ErrInvalidChart = util.NewInvalidArgumentErrorf("chart is invalid") 28 ) 29 30 // Metadata for a Chart file. This models the structure of a Chart.yaml file. 31 type Metadata struct { 32 APIVersion string `json:"api_version" yaml:"apiVersion"` 33 Type string `json:"type,omitempty" yaml:"type,omitempty"` 34 Name string `json:"name" yaml:"name"` 35 Version string `json:"version" yaml:"version"` 36 AppVersion string `json:"app_version,omitempty" yaml:"appVersion,omitempty"` 37 Home string `json:"home,omitempty" yaml:"home,omitempty"` 38 Sources []string `json:"sources,omitempty" yaml:"sources,omitempty"` 39 Description string `json:"description,omitempty" yaml:"description,omitempty"` 40 Keywords []string `json:"keywords,omitempty" yaml:"keywords,omitempty"` 41 Maintainers []*Maintainer `json:"maintainers,omitempty" yaml:"maintainers,omitempty"` 42 Icon string `json:"icon,omitempty" yaml:"icon,omitempty"` 43 Condition string `json:"condition,omitempty" yaml:"condition,omitempty"` 44 Tags string `json:"tags,omitempty" yaml:"tags,omitempty"` 45 Deprecated bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"` 46 Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"` 47 KubeVersion string `json:"kube_version,omitempty" yaml:"kubeVersion,omitempty"` 48 Dependencies []*Dependency `json:"dependencies,omitempty" yaml:"dependencies,omitempty"` 49 } 50 51 type Maintainer struct { 52 Name string `json:"name,omitempty" yaml:"name,omitempty"` 53 Email string `json:"email,omitempty" yaml:"email,omitempty"` 54 URL string `json:"url,omitempty" yaml:"url,omitempty"` 55 } 56 57 type Dependency struct { 58 Name string `json:"name" yaml:"name"` 59 Version string `json:"version,omitempty" yaml:"version,omitempty"` 60 Repository string `json:"repository" yaml:"repository"` 61 Condition string `json:"condition,omitempty" yaml:"condition,omitempty"` 62 Tags []string `json:"tags,omitempty" yaml:"tags,omitempty"` 63 Enabled bool `json:"enabled,omitempty" yaml:"enabled,omitempty"` 64 ImportValues []interface{} `json:"import_values,omitempty" yaml:"import-values,omitempty"` 65 Alias string `json:"alias,omitempty" yaml:"alias,omitempty"` 66 } 67 68 // ParseChartArchive parses the metadata of a Helm archive 69 func ParseChartArchive(r io.Reader) (*Metadata, error) { 70 gzr, err := gzip.NewReader(r) 71 if err != nil { 72 return nil, err 73 } 74 defer gzr.Close() 75 76 tr := tar.NewReader(gzr) 77 for { 78 hd, err := tr.Next() 79 if err == io.EOF { 80 break 81 } 82 if err != nil { 83 return nil, err 84 } 85 86 if hd.Typeflag != tar.TypeReg { 87 continue 88 } 89 90 if hd.FileInfo().Name() == "Chart.yaml" { 91 if strings.Count(hd.Name, "/") != 1 { 92 continue 93 } 94 95 return ParseChartFile(tr) 96 } 97 } 98 99 return nil, ErrMissingChartFile 100 } 101 102 // ParseChartFile parses a Chart.yaml file to retrieve the metadata of a Helm chart 103 func ParseChartFile(r io.Reader) (*Metadata, error) { 104 var metadata *Metadata 105 if err := yaml.NewDecoder(r).Decode(&metadata); err != nil { 106 return nil, err 107 } 108 109 if metadata.APIVersion == "" { 110 return nil, ErrInvalidChart 111 } 112 113 if metadata.Type != "" && metadata.Type != "application" && metadata.Type != "library" { 114 return nil, ErrInvalidChart 115 } 116 117 if metadata.Name == "" { 118 return nil, ErrInvalidName 119 } 120 121 if _, err := version.NewSemver(metadata.Version); err != nil { 122 return nil, ErrInvalidVersion 123 } 124 125 if !validation.IsValidURL(metadata.Home) { 126 metadata.Home = "" 127 } 128 129 return metadata, nil 130 }